@testream/dotnet-reporter 0.4.6 → 0.5.0

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/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export { parseTrxFile, parseTrxFiles } from './trx-parser';
2
- export { uploadToApi, detectGitContext, defaultLogger } from './uploader';
3
- export type { Logger, UploadToApiOptions } from './uploader';
2
+ export { uploadToApi, detectGitContext } from './uploader';
4
3
  export type { DotnetReporterConfig } from './types';
5
- export type { CTRFReport, CTRFTest, CTRFSummary, CTRFResults, UploadResult, } from '@jira-test-manager/shared-types';
4
+ export type { CTRFReport, CTRFTest, CTRFSummary, CTRFResults, UploadResult, UploadTestRunOptions, } from '@jira-test-manager/shared-types';
@@ -1 +1 @@
1
- {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/jira-test-manager/jira-test-manager/packages/dotnet-reporter/src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC1E,YAAY,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC7D,YAAY,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AACpD,YAAY,EACV,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,YAAY,GACb,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/jira-test-manager/jira-test-manager/packages/dotnet-reporter/src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC3D,YAAY,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AACpD,YAAY,EACV,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,YAAY,EACZ,oBAAoB,GACrB,MAAM,iCAAiC,CAAC"}
package/dist/index.js CHANGED
@@ -2275,15 +2275,194 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
2275
2275
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
2276
2276
  };
2277
2277
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2278
- exports.detectCIContext = void 0;
2278
+ exports.uploadArtifacts = exports.uploadTestRun = exports.detectCIContext = void 0;
2279
2279
  // CTRF types
2280
2280
  __exportStar(__nccwpck_require__(827), exports);
2281
2281
  var ci_detection_1 = __nccwpck_require__(406);
2282
2282
  Object.defineProperty(exports, "detectCIContext", ({ enumerable: true, get: function () { return ci_detection_1.detectCIContext; } }));
2283
+ var upload_1 = __nccwpck_require__(969);
2284
+ Object.defineProperty(exports, "uploadTestRun", ({ enumerable: true, get: function () { return upload_1.uploadTestRun; } }));
2285
+ Object.defineProperty(exports, "uploadArtifacts", ({ enumerable: true, get: function () { return upload_1.uploadArtifacts; } }));
2283
2286
  //# sourceMappingURL=index.js.map
2284
2287
 
2285
2288
  /***/ }),
2286
2289
 
2290
+ /***/ 969:
2291
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
2292
+
2293
+ "use strict";
2294
+
2295
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
2296
+ exports.uploadTestRun = uploadTestRun;
2297
+ exports.uploadArtifacts = uploadArtifacts;
2298
+ const DEFAULT_API_URL = 'https://test-manager-backend.fly.dev';
2299
+ /**
2300
+ * Upload test run to Testream backend API
2301
+ */
2302
+ async function uploadTestRun(options) {
2303
+ const { report, apiKey, apiUrl = DEFAULT_API_URL } = options;
2304
+ // Ensure reportId exists
2305
+ if (!report.reportId) {
2306
+ report.reportId = crypto.randomUUID();
2307
+ }
2308
+ // Build type-safe IngestRequest payload
2309
+ const ingestPayload = {
2310
+ report,
2311
+ reportId: report.reportId,
2312
+ commitSha: options.commitSha,
2313
+ branch: options.branch,
2314
+ repositoryUrl: options.repositoryUrl,
2315
+ buildName: options.buildName,
2316
+ buildNumber: options.buildNumber,
2317
+ buildUrl: options.buildUrl,
2318
+ testEnvironment: options.testEnvironment,
2319
+ appName: options.appName,
2320
+ appVersion: options.appVersion,
2321
+ testType: options.testType,
2322
+ };
2323
+ // Professional logging
2324
+ console.log('Uploading test results...');
2325
+ let response;
2326
+ try {
2327
+ response = await fetch(`${apiUrl}/api/v1/ingest`, {
2328
+ method: 'POST',
2329
+ headers: {
2330
+ 'X-API-KEY': apiKey,
2331
+ 'Content-Type': 'application/json',
2332
+ },
2333
+ body: JSON.stringify(ingestPayload),
2334
+ });
2335
+ }
2336
+ catch (error) {
2337
+ const errorMessage = error instanceof Error ? error.message : String(error);
2338
+ return {
2339
+ success: false,
2340
+ reportId: report.reportId,
2341
+ error: `Connection failed: ${errorMessage}`,
2342
+ };
2343
+ }
2344
+ // Handle 409 (report already exists) - idempotent
2345
+ if (response.status === 409) {
2346
+ console.warn('Report already exists (workflow may have been re-run)');
2347
+ return {
2348
+ success: true,
2349
+ reportId: report.reportId,
2350
+ summary: {
2351
+ passed: report.results.summary.passed,
2352
+ failed: report.results.summary.failed,
2353
+ skipped: report.results.summary.skipped,
2354
+ total: report.results.summary.tests,
2355
+ },
2356
+ alreadyExists: true,
2357
+ };
2358
+ }
2359
+ // Handle other errors
2360
+ if (!response.ok) {
2361
+ const errorText = await response.text();
2362
+ return {
2363
+ success: false,
2364
+ reportId: report.reportId,
2365
+ error: `Upload failed (HTTP ${response.status}): ${errorText}`,
2366
+ };
2367
+ }
2368
+ // Success
2369
+ const result = (await response.json());
2370
+ console.log(`✓ Test results uploaded successfully`);
2371
+ console.log(` Report ID: ${result.reportId}`);
2372
+ console.log(` Test Run ID: ${result.testRunId}`);
2373
+ console.log(` Tests: ${result.summary.passed}/${result.summary.total} passed`);
2374
+ return {
2375
+ success: true,
2376
+ reportId: result.reportId,
2377
+ testRunId: result.testRunId,
2378
+ summary: {
2379
+ passed: result.summary.passed,
2380
+ failed: result.summary.failed,
2381
+ skipped: result.summary.skipped,
2382
+ total: result.summary.total,
2383
+ },
2384
+ testResults: result.testResults,
2385
+ };
2386
+ }
2387
+ /**
2388
+ * Upload test artifacts (screenshots, videos, etc.) to Testream backend API
2389
+ */
2390
+ async function uploadArtifacts(options) {
2391
+ const { reportId, apiKey, testResults, apiUrl = DEFAULT_API_URL } = options;
2392
+ let uploadedCount = 0;
2393
+ for (const testResult of testResults) {
2394
+ for (const attachment of testResult.attachments) {
2395
+ try {
2396
+ const success = await uploadSingleArtifact({
2397
+ testResultId: testResult.testResultId,
2398
+ attachment,
2399
+ reportId,
2400
+ apiKey,
2401
+ apiUrl,
2402
+ });
2403
+ if (success)
2404
+ uploadedCount++;
2405
+ }
2406
+ catch (error) {
2407
+ const errorMessage = error instanceof Error ? error.message : String(error);
2408
+ console.error(`Failed to upload artifact ${attachment.name}: ${errorMessage}`);
2409
+ }
2410
+ }
2411
+ }
2412
+ if (uploadedCount > 0) {
2413
+ console.log(`✓ Uploaded ${uploadedCount} artifact(s)`);
2414
+ }
2415
+ return uploadedCount;
2416
+ }
2417
+ async function uploadSingleArtifact(options) {
2418
+ const { testResultId, attachment, reportId, apiKey, apiUrl } = options;
2419
+ // Dynamically import fs for Node.js environments
2420
+ const fs = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__, 943, 23));
2421
+ const path = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__, 928, 23));
2422
+ const filePath = path.resolve(attachment.path);
2423
+ // Check if file exists
2424
+ try {
2425
+ await fs.access(filePath);
2426
+ }
2427
+ catch {
2428
+ console.warn(`Artifact not found: ${path.basename(filePath)}`);
2429
+ return false;
2430
+ }
2431
+ // Read file
2432
+ let fileBuffer;
2433
+ try {
2434
+ fileBuffer = await fs.readFile(filePath);
2435
+ }
2436
+ catch (error) {
2437
+ const errorMessage = error instanceof Error ? error.message : String(error);
2438
+ throw new Error(`Failed to read file: ${errorMessage}`);
2439
+ }
2440
+ // Create native FormData with Blob
2441
+ const blob = new Blob([fileBuffer], { type: attachment.contentType });
2442
+ const formData = new FormData();
2443
+ formData.append('testResultId', testResultId);
2444
+ formData.append('ctrfAttachmentName', attachment.name);
2445
+ formData.append('file', blob, path.basename(filePath));
2446
+ // Upload to API
2447
+ const uploadUrl = `${apiUrl}/api/v1/artifacts/${reportId}`;
2448
+ const response = await fetch(uploadUrl, {
2449
+ method: 'POST',
2450
+ headers: {
2451
+ 'X-API-KEY': apiKey,
2452
+ // Don't set Content-Type - fetch sets it with boundary
2453
+ },
2454
+ body: formData,
2455
+ });
2456
+ if (!response.ok) {
2457
+ const errorText = await response.text();
2458
+ throw new Error(`HTTP ${response.status}: ${errorText}`);
2459
+ }
2460
+ return true;
2461
+ }
2462
+ //# sourceMappingURL=upload.js.map
2463
+
2464
+ /***/ }),
2465
+
2287
2466
  /***/ 328:
2288
2467
  /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
2289
2468
 
@@ -2521,7 +2700,7 @@ async function findTrxFiles(pattern) {
2521
2700
  * Run dotnet test and return the path to generated TRX file
2522
2701
  */
2523
2702
  async function runDotnetTest(projectPath, additionalArgs = []) {
2524
- const logger = uploader_1.defaultLogger;
2703
+ const logger = console;
2525
2704
  // Create temp directory for TRX output
2526
2705
  const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'dotnet-reporter-'));
2527
2706
  const trxFileName = `results-${Date.now()}.trx`;
@@ -2579,7 +2758,7 @@ async function main() {
2579
2758
  if (!options) {
2580
2759
  process.exit(1);
2581
2760
  }
2582
- const logger = uploader_1.defaultLogger;
2761
+ const logger = console;
2583
2762
  try {
2584
2763
  let trxPath;
2585
2764
  // Either use provided TRX path or run dotnet test
@@ -2631,7 +2810,6 @@ async function main() {
2631
2810
  // Upload to API
2632
2811
  const result = await (0, uploader_1.uploadToApi)({
2633
2812
  report,
2634
- projectKey: options.projectKey,
2635
2813
  apiKey: options.apiKey,
2636
2814
  // Git context
2637
2815
  branch,
@@ -2646,14 +2824,13 @@ async function main() {
2646
2824
  appName: options.appName,
2647
2825
  appVersion: options.appVersion,
2648
2826
  testType: options.testType,
2649
- logger,
2650
2827
  });
2651
2828
  if (!result.success) {
2652
2829
  if (options.failOnUploadError) {
2653
2830
  process.exit(1);
2654
2831
  }
2655
2832
  else {
2656
- logger.warning('Upload failed but continuing (use --fail-on-error to fail on upload errors)');
2833
+ logger.warn('Upload failed but continuing (use --fail-on-error to fail on upload errors)');
2657
2834
  }
2658
2835
  }
2659
2836
  }
@@ -2981,173 +3158,27 @@ async function parseTrxFiles(trxPaths) {
2981
3158
  "use strict";
2982
3159
 
2983
3160
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2984
- exports.detectGitContext = exports.defaultLogger = void 0;
3161
+ exports.detectGitContext = void 0;
2985
3162
  exports.uploadToApi = uploadToApi;
2986
3163
  const shared_types_1 = __nccwpck_require__(322);
2987
- const crypto_1 = __nccwpck_require__(982);
2988
- /**
2989
- * Hardcoded API URL for Testream backend
2990
- */
2991
- const API_URL = 'https://test-manager-backend.fly.dev';
2992
- /**
2993
- * Default console logger
2994
- */
2995
- exports.defaultLogger = {
2996
- info: (msg) => console.log(msg),
2997
- warning: (msg) => console.warn(msg),
2998
- error: (msg) => console.error(msg),
2999
- };
3000
3164
  /**
3001
3165
  * Upload CTRF report to Testream API
3002
3166
  */
3003
3167
  async function uploadToApi(options) {
3004
- const { report, projectKey, apiKey, commitSha = '', branch = '', repositoryUrl = '', buildName, buildNumber, buildUrl, testEnvironment, appName, appVersion, testType, logger = exports.defaultLogger, } = options;
3005
- // Ensure reportId exists
3006
- if (!report.reportId) {
3007
- report.reportId = (0, crypto_1.randomUUID)();
3008
- logger.info(`Generated reportId: ${report.reportId}`);
3009
- }
3010
- try {
3011
- logger.info('='.repeat(60));
3012
- logger.info('Testream - .NET Test Results Upload');
3013
- logger.info('='.repeat(60));
3014
- logger.info(`Project Key: ${projectKey}`);
3015
- logger.info(`Test Tool: ${report.results.tool.name}`);
3016
- logger.info('');
3017
- logger.info(`Test Summary:`);
3018
- logger.info(` Total: ${report.results.summary.tests}`);
3019
- logger.info(` Passed: ${report.results.summary.passed}`);
3020
- logger.info(` Failed: ${report.results.summary.failed}`);
3021
- logger.info(` Skipped: ${report.results.summary.skipped}`);
3022
- logger.info('');
3023
- // Log git context if provided
3024
- if (branch || commitSha || repositoryUrl) {
3025
- logger.info(`Git Context:`);
3026
- if (branch)
3027
- logger.info(` Branch: ${branch}`);
3028
- if (commitSha)
3029
- logger.info(` Commit: ${commitSha.substring(0, 7)}`);
3030
- if (repositoryUrl)
3031
- logger.info(` Repository: ${repositoryUrl}`);
3032
- logger.info('');
3033
- }
3034
- // Log build info if provided
3035
- if (buildName || buildNumber || buildUrl) {
3036
- logger.info(`Build Info:`);
3037
- if (buildName)
3038
- logger.info(` Name: ${buildName}`);
3039
- if (buildNumber)
3040
- logger.info(` Number: ${buildNumber}`);
3041
- if (buildUrl)
3042
- logger.info(` URL: ${buildUrl}`);
3043
- logger.info('');
3044
- }
3045
- // Log environment info if provided
3046
- if (testEnvironment || appName || appVersion || testType) {
3047
- logger.info(`Environment:`);
3048
- if (testEnvironment)
3049
- logger.info(` Environment: ${testEnvironment}`);
3050
- if (appName)
3051
- logger.info(` App: ${appName}`);
3052
- if (appVersion)
3053
- logger.info(` Version: ${appVersion}`);
3054
- if (testType)
3055
- logger.info(` Test Type: ${testType}`);
3056
- logger.info('');
3057
- }
3058
- // Prepare payload with all metadata
3059
- const ingestPayload = {
3060
- report,
3061
- reportId: report.reportId,
3062
- projectKey,
3063
- // Git context
3064
- commitSha,
3065
- branch,
3066
- repositoryUrl,
3067
- // Build metadata
3068
- buildName,
3069
- buildNumber,
3070
- buildUrl,
3071
- // Environment metadata
3072
- testEnvironment,
3073
- appName,
3074
- appVersion,
3075
- testType,
3076
- };
3077
- // Upload to API
3078
- logger.info(`Uploading test results...`);
3079
- logger.info(` Report ID: ${report.reportId}`);
3080
- let response;
3081
- try {
3082
- response = await fetch(`${API_URL}/api/v1/ingest`, {
3083
- method: 'POST',
3084
- headers: {
3085
- 'X-API-KEY': apiKey,
3086
- 'Content-Type': 'application/json',
3087
- },
3088
- body: JSON.stringify(ingestPayload),
3089
- });
3090
- }
3091
- catch (error) {
3092
- const errorMessage = error instanceof Error ? error.message : String(error);
3093
- throw new Error(`Failed to connect to API: ${errorMessage}`);
3094
- }
3095
- // Log response status for debugging
3096
- logger.info(` Response status: ${response.status}`);
3097
- // Handle errors
3098
- if (!response.ok) {
3099
- const responseText = await response.text();
3100
- let errorData = null;
3101
- try {
3102
- errorData = JSON.parse(responseText);
3103
- }
3104
- catch {
3105
- // Not JSON
3106
- }
3107
- // Handle 409 (already exists)
3108
- if (response.status === 409) {
3109
- logger.warning(`Report already exists: ${errorData?.reportId || 'unknown'}`);
3110
- logger.info('This is expected if the workflow was re-run');
3111
- return {
3112
- success: true,
3113
- reportId: errorData?.reportId || report.reportId,
3114
- summary: {
3115
- passed: report.results.summary.passed,
3116
- failed: report.results.summary.failed,
3117
- skipped: report.results.summary.skipped,
3118
- total: report.results.summary.tests,
3119
- },
3120
- };
3121
- }
3122
- // Other errors
3123
- const errorMessage = errorData?.error
3124
- ? `${errorData.error}${errorData.details ? `: ${errorData.details}` : ''}`
3125
- : responseText || `HTTP ${response.status}`;
3126
- throw new Error(`API ingest failed (${response.status}): ${errorMessage}`);
3127
- }
3128
- const result = (await response.json());
3129
- logger.info('');
3130
- logger.info('='.repeat(60));
3131
- logger.info('Upload completed successfully');
3132
- logger.info(` Report ID: ${result.reportId}`);
3133
- logger.info(` Test Run ID: ${result.testRunId}`);
3134
- logger.info('='.repeat(60));
3135
- return {
3136
- success: true,
3137
- reportId: result.reportId,
3138
- testRunId: result.testRunId,
3139
- summary: result.summary,
3140
- };
3141
- }
3142
- catch (error) {
3143
- const errorMessage = error instanceof Error ? error.message : String(error);
3144
- logger.error(`Upload failed: ${errorMessage}`);
3145
- return {
3146
- success: false,
3147
- reportId: '',
3148
- error: errorMessage,
3149
- };
3150
- }
3168
+ return (0, shared_types_1.uploadTestRun)({
3169
+ report: options.report,
3170
+ apiKey: options.apiKey,
3171
+ commitSha: options.commitSha,
3172
+ branch: options.branch,
3173
+ repositoryUrl: options.repositoryUrl,
3174
+ buildName: options.buildName,
3175
+ buildNumber: options.buildNumber,
3176
+ buildUrl: options.buildUrl,
3177
+ testEnvironment: options.testEnvironment,
3178
+ appName: options.appName,
3179
+ appVersion: options.appVersion,
3180
+ testType: options.testType,
3181
+ });
3151
3182
  }
3152
3183
  // Keep old function name for backwards compatibility
3153
3184
  exports.detectGitContext = shared_types_1.detectCIContext;
@@ -3163,14 +3194,6 @@ module.exports = require("child_process");
3163
3194
 
3164
3195
  /***/ }),
3165
3196
 
3166
- /***/ 982:
3167
- /***/ ((module) => {
3168
-
3169
- "use strict";
3170
- module.exports = require("crypto");
3171
-
3172
- /***/ }),
3173
-
3174
3197
  /***/ 896:
3175
3198
  /***/ ((module) => {
3176
3199
 
@@ -11526,6 +11549,64 @@ exports.PathScurry = process.platform === 'win32' ? PathScurryWin32
11526
11549
  /******/ }
11527
11550
  /******/
11528
11551
  /************************************************************************/
11552
+ /******/ /* webpack/runtime/create fake namespace object */
11553
+ /******/ (() => {
11554
+ /******/ var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__);
11555
+ /******/ var leafPrototypes;
11556
+ /******/ // create a fake namespace object
11557
+ /******/ // mode & 1: value is a module id, require it
11558
+ /******/ // mode & 2: merge all properties of value into the ns
11559
+ /******/ // mode & 4: return value when already ns object
11560
+ /******/ // mode & 16: return value when it's Promise-like
11561
+ /******/ // mode & 8|1: behave like require
11562
+ /******/ __nccwpck_require__.t = function(value, mode) {
11563
+ /******/ if(mode & 1) value = this(value);
11564
+ /******/ if(mode & 8) return value;
11565
+ /******/ if(typeof value === 'object' && value) {
11566
+ /******/ if((mode & 4) && value.__esModule) return value;
11567
+ /******/ if((mode & 16) && typeof value.then === 'function') return value;
11568
+ /******/ }
11569
+ /******/ var ns = Object.create(null);
11570
+ /******/ __nccwpck_require__.r(ns);
11571
+ /******/ var def = {};
11572
+ /******/ leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)];
11573
+ /******/ for(var current = mode & 2 && value; typeof current == 'object' && !~leafPrototypes.indexOf(current); current = getProto(current)) {
11574
+ /******/ Object.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key])));
11575
+ /******/ }
11576
+ /******/ def['default'] = () => (value);
11577
+ /******/ __nccwpck_require__.d(ns, def);
11578
+ /******/ return ns;
11579
+ /******/ };
11580
+ /******/ })();
11581
+ /******/
11582
+ /******/ /* webpack/runtime/define property getters */
11583
+ /******/ (() => {
11584
+ /******/ // define getter functions for harmony exports
11585
+ /******/ __nccwpck_require__.d = (exports, definition) => {
11586
+ /******/ for(var key in definition) {
11587
+ /******/ if(__nccwpck_require__.o(definition, key) && !__nccwpck_require__.o(exports, key)) {
11588
+ /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
11589
+ /******/ }
11590
+ /******/ }
11591
+ /******/ };
11592
+ /******/ })();
11593
+ /******/
11594
+ /******/ /* webpack/runtime/hasOwnProperty shorthand */
11595
+ /******/ (() => {
11596
+ /******/ __nccwpck_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
11597
+ /******/ })();
11598
+ /******/
11599
+ /******/ /* webpack/runtime/make namespace object */
11600
+ /******/ (() => {
11601
+ /******/ // define __esModule on exports
11602
+ /******/ __nccwpck_require__.r = (exports) => {
11603
+ /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
11604
+ /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
11605
+ /******/ }
11606
+ /******/ Object.defineProperty(exports, '__esModule', { value: true });
11607
+ /******/ };
11608
+ /******/ })();
11609
+ /******/
11529
11610
  /******/ /* webpack/runtime/compat */
11530
11611
  /******/
11531
11612
  /******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";