@microsoft/sentinel-cli 0.1.0 → 0.3.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.js +3536 -612
- package/package.json +9 -2
package/dist/index.js
CHANGED
|
@@ -44,7 +44,7 @@ var require_correlationService = __commonJS({
|
|
|
44
44
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
45
45
|
exports2.CorrelationService = void 0;
|
|
46
46
|
var crypto_1 = require("crypto");
|
|
47
|
-
var
|
|
47
|
+
var CorrelationService17 = class {
|
|
48
48
|
/**
|
|
49
49
|
* Creates a new correlation context with a unique ID for request tracking.
|
|
50
50
|
* @returns A UUID string to be used as a correlation ID in API requests and telemetry.
|
|
@@ -61,7 +61,7 @@ var require_correlationService = __commonJS({
|
|
|
61
61
|
return response?.headers?.["x-ms-correlation-request-id"];
|
|
62
62
|
}
|
|
63
63
|
};
|
|
64
|
-
exports2.CorrelationService =
|
|
64
|
+
exports2.CorrelationService = CorrelationService17;
|
|
65
65
|
}
|
|
66
66
|
});
|
|
67
67
|
|
|
@@ -159,6 +159,7 @@ var require_requestService = __commonJS({
|
|
|
159
159
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
160
160
|
exports2.RequestService = exports2.DEFAULT_RETRY_OPTIONS = void 0;
|
|
161
161
|
exports2.extractErrorInfo = extractErrorInfo;
|
|
162
|
+
var https_1 = __importDefault(require("https"));
|
|
162
163
|
var axios_1 = __importDefault(require("axios"));
|
|
163
164
|
var correlationService_1 = require_correlationService();
|
|
164
165
|
var httpConstants_1 = require_httpConstants();
|
|
@@ -185,13 +186,19 @@ var require_requestService = __commonJS({
|
|
|
185
186
|
baseDelayMs: 1e3,
|
|
186
187
|
maxDelayMs: 3e4,
|
|
187
188
|
retryableStatusCodes: Object.freeze([429, 500, 502, 503, 504]),
|
|
188
|
-
retryableErrors: Object.freeze(["ECONNRESET", "ETIMEDOUT", "ENOTFOUND", "ECONNABORTED"])
|
|
189
|
+
retryableErrors: Object.freeze(["ECONNRESET", "ETIMEDOUT", "ENOTFOUND", "ECONNABORTED"]),
|
|
190
|
+
retryableErrorMessages: Object.freeze([
|
|
191
|
+
"socket disconnected",
|
|
192
|
+
"socket hang up",
|
|
193
|
+
"client network socket disconnected"
|
|
194
|
+
])
|
|
189
195
|
});
|
|
190
|
-
var
|
|
196
|
+
var HTTPS_AGENT = new https_1.default.Agent({ keepAlive: false });
|
|
197
|
+
var RequestService5 = class {
|
|
191
198
|
telemetry;
|
|
192
199
|
headerBuilder;
|
|
193
|
-
constructor(
|
|
194
|
-
this.telemetry =
|
|
200
|
+
constructor(telemetry2, headerBuilder) {
|
|
201
|
+
this.telemetry = telemetry2;
|
|
195
202
|
this.headerBuilder = headerBuilder;
|
|
196
203
|
}
|
|
197
204
|
async get(options) {
|
|
@@ -273,7 +280,12 @@ var require_requestService = __commonJS({
|
|
|
273
280
|
mainSpan.addAttributes({ success: "true" });
|
|
274
281
|
return result;
|
|
275
282
|
} catch (error) {
|
|
276
|
-
|
|
283
|
+
const decision = this.shouldRetry(error, retryOptions ?? {});
|
|
284
|
+
if (attempt < clampedMaxRetries && decision.retry) {
|
|
285
|
+
mainSpan.addAttributes({
|
|
286
|
+
[`retry.${attempt}.reason`]: decision.reason ?? "",
|
|
287
|
+
[`retry.${attempt}.detail`]: decision.detail ?? ""
|
|
288
|
+
});
|
|
277
289
|
await this.sleep(this.calculateRetryDelay(attempt, clampedBaseDelayMs, clampedMaxDelayMs));
|
|
278
290
|
continue;
|
|
279
291
|
}
|
|
@@ -350,7 +362,8 @@ var require_requestService = __commonJS({
|
|
|
350
362
|
url,
|
|
351
363
|
method: options?.method?.toLowerCase() || "get",
|
|
352
364
|
headers: { ...options?.headers },
|
|
353
|
-
data: options?.body
|
|
365
|
+
data: options?.body,
|
|
366
|
+
httpsAgent: HTTPS_AGENT
|
|
354
367
|
};
|
|
355
368
|
if (timeoutMs !== void 0) {
|
|
356
369
|
axiosConfig.timeout = timeoutMs;
|
|
@@ -402,15 +415,24 @@ var require_requestService = __commonJS({
|
|
|
402
415
|
shouldRetry(error, retryOptions) {
|
|
403
416
|
const retryableStatusCodes = retryOptions.retryableStatusCodes ?? exports2.DEFAULT_RETRY_OPTIONS.retryableStatusCodes;
|
|
404
417
|
const retryableErrors = retryOptions.retryableErrors ?? exports2.DEFAULT_RETRY_OPTIONS.retryableErrors;
|
|
418
|
+
const retryableErrorMessages = retryOptions.retryableErrorMessages ?? exports2.DEFAULT_RETRY_OPTIONS.retryableErrorMessages;
|
|
405
419
|
const httpError = error;
|
|
406
420
|
if (typeof httpError?.statusCode === "number") {
|
|
407
|
-
return retryableStatusCodes.includes(httpError.statusCode);
|
|
421
|
+
return retryableStatusCodes.includes(httpError.statusCode) ? { retry: true, reason: "statusCode", detail: String(httpError.statusCode) } : { retry: false };
|
|
408
422
|
}
|
|
409
423
|
const codedError = error;
|
|
410
|
-
if (codedError?.code) {
|
|
411
|
-
return
|
|
424
|
+
if (codedError?.code && retryableErrors.includes(codedError.code)) {
|
|
425
|
+
return { retry: true, reason: "errorCode", detail: codedError.code };
|
|
412
426
|
}
|
|
413
|
-
|
|
427
|
+
const errorMessage = error?.message;
|
|
428
|
+
if (typeof errorMessage === "string" && errorMessage.length > 0) {
|
|
429
|
+
const lowerMessage = errorMessage.toLowerCase();
|
|
430
|
+
const matchedPattern = retryableErrorMessages.find((pattern) => lowerMessage.includes(pattern.toLowerCase()));
|
|
431
|
+
if (matchedPattern) {
|
|
432
|
+
return { retry: true, reason: "errorMessage", detail: matchedPattern };
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
return { retry: false };
|
|
414
436
|
}
|
|
415
437
|
/**
|
|
416
438
|
* Exponential backoff with 10% random jitter.
|
|
@@ -423,7 +445,7 @@ var require_requestService = __commonJS({
|
|
|
423
445
|
return Math.min(exponentialDelay + jitter, maxDelayMs);
|
|
424
446
|
}
|
|
425
447
|
sleep(ms) {
|
|
426
|
-
return new Promise((
|
|
448
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
427
449
|
}
|
|
428
450
|
// -------------------------------------------------------------------------
|
|
429
451
|
// URL helpers
|
|
@@ -439,7 +461,7 @@ var require_requestService = __commonJS({
|
|
|
439
461
|
return urlObj.toString();
|
|
440
462
|
}
|
|
441
463
|
};
|
|
442
|
-
exports2.RequestService =
|
|
464
|
+
exports2.RequestService = RequestService5;
|
|
443
465
|
function getPathFromUrl(url) {
|
|
444
466
|
const urlObject = new URL(url);
|
|
445
467
|
return urlObject.pathname;
|
|
@@ -466,20 +488,74 @@ var require_client = __commonJS({
|
|
|
466
488
|
o[k2] = m[k];
|
|
467
489
|
}));
|
|
468
490
|
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
469
|
-
for (var
|
|
491
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
470
492
|
};
|
|
471
493
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
472
494
|
__exportStar(require_requestService(), exports2);
|
|
473
495
|
}
|
|
474
496
|
});
|
|
475
497
|
|
|
476
|
-
// ../../packages/common/dist/src/constants.js
|
|
498
|
+
// ../../packages/common/dist/src/constants/jobEventNames.js
|
|
499
|
+
var require_jobEventNames = __commonJS({
|
|
500
|
+
"../../packages/common/dist/src/constants/jobEventNames.js"(exports2) {
|
|
501
|
+
"use strict";
|
|
502
|
+
init_cjs_shims();
|
|
503
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
504
|
+
exports2.JobApiEvents = void 0;
|
|
505
|
+
exports2.JobApiEvents = {
|
|
506
|
+
LOAD_JOBS: "JobsPanel.Load.Jobs",
|
|
507
|
+
CREATE_JOB: "Jobs.Create.Job",
|
|
508
|
+
GET_JOB: "Jobs.Get.Job",
|
|
509
|
+
DELETE_JOB: "Jobs.Delete.Job",
|
|
510
|
+
DISABLE_JOB: "Jobs.Disable.Job",
|
|
511
|
+
ENABLE_JOB: "Jobs.Enable.Job",
|
|
512
|
+
LIST_JOB_RUNS: "Jobs.List.Runs",
|
|
513
|
+
GET_JOB_RUN: "Jobs.Get.Run",
|
|
514
|
+
START_JOB_RUN: "Jobs.Start.Run",
|
|
515
|
+
CANCEL_JOB_RUN: "Jobs.Cancel.Run"
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
// ../../packages/common/dist/src/constants/lakeEventNames.js
|
|
521
|
+
var require_lakeEventNames = __commonJS({
|
|
522
|
+
"../../packages/common/dist/src/constants/lakeEventNames.js"(exports2) {
|
|
523
|
+
"use strict";
|
|
524
|
+
init_cjs_shims();
|
|
525
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
526
|
+
exports2.LakeApiEvents = void 0;
|
|
527
|
+
exports2.LakeApiEvents = {
|
|
528
|
+
LOAD_TABLES: "LakeTablesPanel.Load.Tables",
|
|
529
|
+
LOAD_DATABASES: "LakeTablesPanel.Load.Databases"
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
// ../../packages/common/dist/src/constants/index.js
|
|
477
535
|
var require_constants = __commonJS({
|
|
478
|
-
"../../packages/common/dist/src/constants.js"(exports2) {
|
|
536
|
+
"../../packages/common/dist/src/constants/index.js"(exports2) {
|
|
479
537
|
"use strict";
|
|
480
538
|
init_cjs_shims();
|
|
539
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
540
|
+
if (k2 === void 0) k2 = k;
|
|
541
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
542
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
543
|
+
desc = { enumerable: true, get: function() {
|
|
544
|
+
return m[k];
|
|
545
|
+
} };
|
|
546
|
+
}
|
|
547
|
+
Object.defineProperty(o, k2, desc);
|
|
548
|
+
}) : (function(o, m, k, k2) {
|
|
549
|
+
if (k2 === void 0) k2 = k;
|
|
550
|
+
o[k2] = m[k];
|
|
551
|
+
}));
|
|
552
|
+
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
553
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
554
|
+
};
|
|
481
555
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
482
556
|
exports2.FulfillmentStatus = exports2.PackageManifestIdValues = exports2.PackageManifestTypes = exports2.CANCEL_DEPLOYMENT_REQUEST_TYPE = exports2.NEW_DEPLOYMENT_REQUEST_TYPE = void 0;
|
|
557
|
+
__exportStar(require_jobEventNames(), exports2);
|
|
558
|
+
__exportStar(require_lakeEventNames(), exports2);
|
|
483
559
|
exports2.NEW_DEPLOYMENT_REQUEST_TYPE = "NewDeploymentRequest";
|
|
484
560
|
exports2.CANCEL_DEPLOYMENT_REQUEST_TYPE = "CancelSubscription";
|
|
485
561
|
var PackageManifestTypes;
|
|
@@ -509,26 +585,26 @@ var require_region = __commonJS({
|
|
|
509
585
|
init_cjs_shims();
|
|
510
586
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
511
587
|
exports2.Region = void 0;
|
|
512
|
-
var
|
|
513
|
-
(function(
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
})(
|
|
588
|
+
var Region14;
|
|
589
|
+
(function(Region15) {
|
|
590
|
+
Region15["NorwayEast"] = "norwayeast";
|
|
591
|
+
Region15["EastUS2EUAP"] = "eastus2euap";
|
|
592
|
+
Region15["AustraliaEast"] = "australiaeast";
|
|
593
|
+
Region15["CanadaCentral"] = "canadacentral";
|
|
594
|
+
Region15["CentralUS"] = "centralus";
|
|
595
|
+
Region15["EastUS"] = "eastus";
|
|
596
|
+
Region15["EastUS2"] = "eastus2";
|
|
597
|
+
Region15["FranceCentral"] = "francecentral";
|
|
598
|
+
Region15["JapanEast"] = "japaneast";
|
|
599
|
+
Region15["NorthEurope"] = "northeurope";
|
|
600
|
+
Region15["SouthCentralUS"] = "southcentralus";
|
|
601
|
+
Region15["UKSouth"] = "uksouth";
|
|
602
|
+
Region15["WestEurope"] = "westeurope";
|
|
603
|
+
Region15["WestUS"] = "westus";
|
|
604
|
+
Region15["WestUS2"] = "westus2";
|
|
605
|
+
Region15["Global"] = "global";
|
|
606
|
+
Region15["Dev"] = "dev";
|
|
607
|
+
})(Region14 || (exports2.Region = Region14 = {}));
|
|
532
608
|
}
|
|
533
609
|
});
|
|
534
610
|
|
|
@@ -539,10 +615,10 @@ var require_securityPlatformEnvironment = __commonJS({
|
|
|
539
615
|
init_cjs_shims();
|
|
540
616
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
541
617
|
exports2.SecurityPlatformEnvironment = void 0;
|
|
542
|
-
var
|
|
543
|
-
(function(
|
|
544
|
-
|
|
545
|
-
})(
|
|
618
|
+
var SecurityPlatformEnvironment21;
|
|
619
|
+
(function(SecurityPlatformEnvironment22) {
|
|
620
|
+
SecurityPlatformEnvironment22["Production"] = "production";
|
|
621
|
+
})(SecurityPlatformEnvironment21 || (exports2.SecurityPlatformEnvironment = SecurityPlatformEnvironment21 = {}));
|
|
546
622
|
}
|
|
547
623
|
});
|
|
548
624
|
|
|
@@ -563,6 +639,8 @@ var require_production = __commonJS({
|
|
|
563
639
|
gatewayAuthResourceUri: "73c2949e-da2d-457a-9607-fcc665198967/.default",
|
|
564
640
|
gatewayEndpoint: "https://api.securityplatform.microsoft.com/",
|
|
565
641
|
aadClientId: DeviceCodeApplicationId,
|
|
642
|
+
armEndpoint: "https://management.azure.com",
|
|
643
|
+
armScope: "https://management.azure.com/.default",
|
|
566
644
|
regions: {
|
|
567
645
|
[region_1.Region.NorwayEast]: buildRegionConfig(region_1.Region.NorwayEast),
|
|
568
646
|
[region_1.Region.EastUS2EUAP]: buildRegionConfig(region_1.Region.EastUS2EUAP),
|
|
@@ -615,7 +693,7 @@ var require_configs = __commonJS({
|
|
|
615
693
|
o[k2] = m[k];
|
|
616
694
|
}));
|
|
617
695
|
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
618
|
-
for (var
|
|
696
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
619
697
|
};
|
|
620
698
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
621
699
|
__exportStar(require_production(), exports2);
|
|
@@ -644,9 +722,9 @@ var require_api_env = __commonJS({
|
|
|
644
722
|
"use strict";
|
|
645
723
|
init_cjs_shims();
|
|
646
724
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
647
|
-
exports2.getApiEnv =
|
|
725
|
+
exports2.getApiEnv = getApiEnv21;
|
|
648
726
|
var helper_1 = require_helper();
|
|
649
|
-
function
|
|
727
|
+
function getApiEnv21(env) {
|
|
650
728
|
return (0, helper_1.getEnvironmentConfig)(env);
|
|
651
729
|
}
|
|
652
730
|
}
|
|
@@ -680,7 +758,7 @@ var require_environments = __commonJS({
|
|
|
680
758
|
o[k2] = m[k];
|
|
681
759
|
}));
|
|
682
760
|
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
683
|
-
for (var
|
|
761
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
684
762
|
};
|
|
685
763
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
686
764
|
__exportStar(require_configs(), exports2);
|
|
@@ -740,11 +818,11 @@ var require_common = __commonJS({
|
|
|
740
818
|
init_cjs_shims();
|
|
741
819
|
var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
742
820
|
function adopt(value) {
|
|
743
|
-
return value instanceof P ? value : new P(function(
|
|
744
|
-
|
|
821
|
+
return value instanceof P ? value : new P(function(resolve2) {
|
|
822
|
+
resolve2(value);
|
|
745
823
|
});
|
|
746
824
|
}
|
|
747
|
-
return new (P || (P = Promise))(function(
|
|
825
|
+
return new (P || (P = Promise))(function(resolve2, reject) {
|
|
748
826
|
function fulfilled(value) {
|
|
749
827
|
try {
|
|
750
828
|
step(generator.next(value));
|
|
@@ -760,7 +838,7 @@ var require_common = __commonJS({
|
|
|
760
838
|
}
|
|
761
839
|
}
|
|
762
840
|
function step(result) {
|
|
763
|
-
result.done ?
|
|
841
|
+
result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
764
842
|
}
|
|
765
843
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
766
844
|
});
|
|
@@ -859,11 +937,11 @@ var require_api = __commonJS({
|
|
|
859
937
|
init_cjs_shims();
|
|
860
938
|
var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
861
939
|
function adopt(value) {
|
|
862
|
-
return value instanceof P ? value : new P(function(
|
|
863
|
-
|
|
940
|
+
return value instanceof P ? value : new P(function(resolve2) {
|
|
941
|
+
resolve2(value);
|
|
864
942
|
});
|
|
865
943
|
}
|
|
866
|
-
return new (P || (P = Promise))(function(
|
|
944
|
+
return new (P || (P = Promise))(function(resolve2, reject) {
|
|
867
945
|
function fulfilled(value) {
|
|
868
946
|
try {
|
|
869
947
|
step(generator.next(value));
|
|
@@ -879,7 +957,7 @@ var require_api = __commonJS({
|
|
|
879
957
|
}
|
|
880
958
|
}
|
|
881
959
|
function step(result) {
|
|
882
|
-
result.done ?
|
|
960
|
+
result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
883
961
|
}
|
|
884
962
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
885
963
|
});
|
|
@@ -2324,7 +2402,7 @@ var require_dist = __commonJS({
|
|
|
2324
2402
|
o[k2] = m[k];
|
|
2325
2403
|
}));
|
|
2326
2404
|
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
2327
|
-
for (var
|
|
2405
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
2328
2406
|
};
|
|
2329
2407
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2330
2408
|
__exportStar(require_api(), exports2);
|
|
@@ -2611,7 +2689,7 @@ var require_factories = __commonJS({
|
|
|
2611
2689
|
o[k2] = m[k];
|
|
2612
2690
|
}));
|
|
2613
2691
|
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
2614
|
-
for (var
|
|
2692
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
2615
2693
|
};
|
|
2616
2694
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2617
2695
|
__exportStar(require_jobPayloadFactory(), exports2);
|
|
@@ -2690,6 +2768,15 @@ var require_jobResponse = __commonJS({
|
|
|
2690
2768
|
}
|
|
2691
2769
|
});
|
|
2692
2770
|
|
|
2771
|
+
// ../../packages/common/dist/src/models/jobs/listJobsResult.js
|
|
2772
|
+
var require_listJobsResult = __commonJS({
|
|
2773
|
+
"../../packages/common/dist/src/models/jobs/listJobsResult.js"(exports2) {
|
|
2774
|
+
"use strict";
|
|
2775
|
+
init_cjs_shims();
|
|
2776
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2777
|
+
}
|
|
2778
|
+
});
|
|
2779
|
+
|
|
2693
2780
|
// ../../packages/common/dist/src/models/jobs/index.js
|
|
2694
2781
|
var require_jobs = __commonJS({
|
|
2695
2782
|
"../../packages/common/dist/src/models/jobs/index.js"(exports2) {
|
|
@@ -2709,7 +2796,7 @@ var require_jobs = __commonJS({
|
|
|
2709
2796
|
o[k2] = m[k];
|
|
2710
2797
|
}));
|
|
2711
2798
|
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
2712
|
-
for (var
|
|
2799
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
2713
2800
|
};
|
|
2714
2801
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2715
2802
|
__exportStar(require_analyticsJobDefinition(), exports2);
|
|
@@ -2719,6 +2806,7 @@ var require_jobs = __commonJS({
|
|
|
2719
2806
|
__exportStar(require_repeatFrequency(), exports2);
|
|
2720
2807
|
__exportStar(require_jobTrigger(), exports2);
|
|
2721
2808
|
__exportStar(require_jobResponse(), exports2);
|
|
2809
|
+
__exportStar(require_listJobsResult(), exports2);
|
|
2722
2810
|
}
|
|
2723
2811
|
});
|
|
2724
2812
|
|
|
@@ -2750,7 +2838,7 @@ var require_lake = __commonJS({
|
|
|
2750
2838
|
o[k2] = m[k];
|
|
2751
2839
|
}));
|
|
2752
2840
|
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
2753
|
-
for (var
|
|
2841
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
2754
2842
|
};
|
|
2755
2843
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2756
2844
|
__exportStar(require_database(), exports2);
|
|
@@ -2833,7 +2921,7 @@ var require_models = __commonJS({
|
|
|
2833
2921
|
o[k2] = m[k];
|
|
2834
2922
|
}));
|
|
2835
2923
|
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
2836
|
-
for (var
|
|
2924
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
2837
2925
|
};
|
|
2838
2926
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2839
2927
|
__exportStar(require_jobs(), exports2);
|
|
@@ -2844,6 +2932,460 @@ var require_models = __commonJS({
|
|
|
2844
2932
|
}
|
|
2845
2933
|
});
|
|
2846
2934
|
|
|
2935
|
+
// ../../packages/common/dist/src/services/tenant/types.js
|
|
2936
|
+
var require_types = __commonJS({
|
|
2937
|
+
"../../packages/common/dist/src/services/tenant/types.js"(exports2) {
|
|
2938
|
+
"use strict";
|
|
2939
|
+
init_cjs_shims();
|
|
2940
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2941
|
+
}
|
|
2942
|
+
});
|
|
2943
|
+
|
|
2944
|
+
// ../../packages/common/dist/src/services/tenant/tenantApiClient.js
|
|
2945
|
+
var require_tenantApiClient = __commonJS({
|
|
2946
|
+
"../../packages/common/dist/src/services/tenant/tenantApiClient.js"(exports2) {
|
|
2947
|
+
"use strict";
|
|
2948
|
+
init_cjs_shims();
|
|
2949
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2950
|
+
exports2.TenantApiClient = void 0;
|
|
2951
|
+
var DEFAULT_ARM_ENDPOINT = "https://management.azure.com";
|
|
2952
|
+
var ARM_API_VERSION = "2020-01-01";
|
|
2953
|
+
var MAX_PAGES = 20;
|
|
2954
|
+
var TENANT_LIST_EVENT = "TenantApiClient.fetchAllTenants";
|
|
2955
|
+
var TenantApiClient2 = class {
|
|
2956
|
+
requestService;
|
|
2957
|
+
tenantsUrl;
|
|
2958
|
+
trustedOrigin;
|
|
2959
|
+
constructor(options) {
|
|
2960
|
+
this.requestService = options.requestService;
|
|
2961
|
+
const armEndpoint = options.armEndpoint ?? DEFAULT_ARM_ENDPOINT;
|
|
2962
|
+
this.tenantsUrl = new URL("/tenants", armEndpoint).toString();
|
|
2963
|
+
this.trustedOrigin = new URL(armEndpoint).origin;
|
|
2964
|
+
}
|
|
2965
|
+
/**
|
|
2966
|
+
* Fetches all tenants accessible to the authenticated user from ARM,
|
|
2967
|
+
* following pagination links until exhausted or the page limit is reached.
|
|
2968
|
+
*
|
|
2969
|
+
* @param accessToken - A valid ARM bearer access token.
|
|
2970
|
+
* @returns An array of {@link ArmTenant} objects.
|
|
2971
|
+
*/
|
|
2972
|
+
async fetchAllTenants(accessToken) {
|
|
2973
|
+
const allTenants = [];
|
|
2974
|
+
let nextUrl = this.tenantsUrl;
|
|
2975
|
+
let params = { "api-version": ARM_API_VERSION };
|
|
2976
|
+
let pageCount = 0;
|
|
2977
|
+
while (nextUrl && pageCount < MAX_PAGES) {
|
|
2978
|
+
pageCount++;
|
|
2979
|
+
const page = await this.requestService.get({
|
|
2980
|
+
url: nextUrl,
|
|
2981
|
+
eventName: TENANT_LIST_EVENT,
|
|
2982
|
+
params,
|
|
2983
|
+
token: accessToken
|
|
2984
|
+
});
|
|
2985
|
+
if (Array.isArray(page.value)) {
|
|
2986
|
+
allTenants.push(...page.value.map(mapArmTenant));
|
|
2987
|
+
}
|
|
2988
|
+
if (page.nextLink) {
|
|
2989
|
+
this.validateNextLink(page.nextLink);
|
|
2990
|
+
nextUrl = page.nextLink;
|
|
2991
|
+
params = {};
|
|
2992
|
+
} else {
|
|
2993
|
+
nextUrl = void 0;
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
if (nextUrl) {
|
|
2997
|
+
throw new Error(`Tenant list is incomplete: maximum page limit of ${MAX_PAGES} reached.`);
|
|
2998
|
+
}
|
|
2999
|
+
return allTenants;
|
|
3000
|
+
}
|
|
3001
|
+
/**
|
|
3002
|
+
* Validates that a pagination URL returned by the ARM API originates from
|
|
3003
|
+
* the trusted ARM endpoint and targets the /tenants path, preventing SSRF
|
|
3004
|
+
* and bearer-token exfiltration to other origins or endpoints.
|
|
3005
|
+
*/
|
|
3006
|
+
validateNextLink(nextLink) {
|
|
3007
|
+
let parsedUrl;
|
|
3008
|
+
try {
|
|
3009
|
+
parsedUrl = new URL(nextLink);
|
|
3010
|
+
} catch {
|
|
3011
|
+
throw new Error(`Invalid nextLink URL: ${nextLink}`);
|
|
3012
|
+
}
|
|
3013
|
+
if (parsedUrl.origin !== this.trustedOrigin) {
|
|
3014
|
+
throw new Error(`Untrusted nextLink origin: expected ${this.trustedOrigin}, got ${parsedUrl.origin}`);
|
|
3015
|
+
}
|
|
3016
|
+
if (parsedUrl.pathname !== "/tenants" && !parsedUrl.pathname.startsWith("/tenants/")) {
|
|
3017
|
+
throw new Error(`Untrusted nextLink path detected: ${parsedUrl.pathname}`);
|
|
3018
|
+
}
|
|
3019
|
+
}
|
|
3020
|
+
};
|
|
3021
|
+
exports2.TenantApiClient = TenantApiClient2;
|
|
3022
|
+
function mapArmTenant(raw) {
|
|
3023
|
+
return {
|
|
3024
|
+
id: raw.id,
|
|
3025
|
+
tenantId: raw.tenantId,
|
|
3026
|
+
displayName: raw.displayName ?? "Unknown Tenant",
|
|
3027
|
+
defaultDomain: raw.defaultDomain ?? "",
|
|
3028
|
+
tenantType: raw.tenantType ?? "AAD",
|
|
3029
|
+
tenantCategory: raw.tenantCategory
|
|
3030
|
+
};
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
3033
|
+
});
|
|
3034
|
+
|
|
3035
|
+
// ../../packages/common/dist/src/services/tenant/index.js
|
|
3036
|
+
var require_tenant = __commonJS({
|
|
3037
|
+
"../../packages/common/dist/src/services/tenant/index.js"(exports2) {
|
|
3038
|
+
"use strict";
|
|
3039
|
+
init_cjs_shims();
|
|
3040
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
3041
|
+
if (k2 === void 0) k2 = k;
|
|
3042
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
3043
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
3044
|
+
desc = { enumerable: true, get: function() {
|
|
3045
|
+
return m[k];
|
|
3046
|
+
} };
|
|
3047
|
+
}
|
|
3048
|
+
Object.defineProperty(o, k2, desc);
|
|
3049
|
+
}) : (function(o, m, k, k2) {
|
|
3050
|
+
if (k2 === void 0) k2 = k;
|
|
3051
|
+
o[k2] = m[k];
|
|
3052
|
+
}));
|
|
3053
|
+
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
3054
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
3055
|
+
};
|
|
3056
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3057
|
+
__exportStar(require_types(), exports2);
|
|
3058
|
+
__exportStar(require_tenantApiClient(), exports2);
|
|
3059
|
+
}
|
|
3060
|
+
});
|
|
3061
|
+
|
|
3062
|
+
// ../../packages/common/dist/src/services/jobs/jobApiClient.js
|
|
3063
|
+
var require_jobApiClient = __commonJS({
|
|
3064
|
+
"../../packages/common/dist/src/services/jobs/jobApiClient.js"(exports2) {
|
|
3065
|
+
"use strict";
|
|
3066
|
+
init_cjs_shims();
|
|
3067
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3068
|
+
exports2.JobApiClient = void 0;
|
|
3069
|
+
var sentinel_graph_job_1 = require_dist();
|
|
3070
|
+
var jobEventNames_1 = require_jobEventNames();
|
|
3071
|
+
var API_VERSION = "2023-09-30-preview";
|
|
3072
|
+
var JOB_PATHS = {
|
|
3073
|
+
JOBS: "/jobs"
|
|
3074
|
+
};
|
|
3075
|
+
var JobApiClient2 = class {
|
|
3076
|
+
requestService;
|
|
3077
|
+
baseUrl;
|
|
3078
|
+
constructor(options) {
|
|
3079
|
+
this.requestService = options.requestService;
|
|
3080
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
3081
|
+
}
|
|
3082
|
+
get jobsUrl() {
|
|
3083
|
+
return `${this.baseUrl}${JOB_PATHS.JOBS}`;
|
|
3084
|
+
}
|
|
3085
|
+
jobUrl(jobName) {
|
|
3086
|
+
return `${this.jobsUrl}/${encodeURIComponent(jobName)}`;
|
|
3087
|
+
}
|
|
3088
|
+
async createJob(jobName, payload, token, requestId) {
|
|
3089
|
+
if (!jobName?.trim()) {
|
|
3090
|
+
throw new Error("Job name is required");
|
|
3091
|
+
}
|
|
3092
|
+
return this.requestService.put({
|
|
3093
|
+
url: this.jobUrl(jobName),
|
|
3094
|
+
params: { "api-version": API_VERSION },
|
|
3095
|
+
eventName: jobEventNames_1.JobApiEvents.CREATE_JOB,
|
|
3096
|
+
body: JSON.stringify(payload),
|
|
3097
|
+
token,
|
|
3098
|
+
requestId
|
|
3099
|
+
});
|
|
3100
|
+
}
|
|
3101
|
+
async getJob(jobName, token, requestId) {
|
|
3102
|
+
if (!jobName?.trim()) {
|
|
3103
|
+
throw new Error("Job name is required");
|
|
3104
|
+
}
|
|
3105
|
+
return this.requestService.get({
|
|
3106
|
+
url: this.jobUrl(jobName),
|
|
3107
|
+
params: { "api-version": API_VERSION },
|
|
3108
|
+
eventName: jobEventNames_1.JobApiEvents.GET_JOB,
|
|
3109
|
+
token,
|
|
3110
|
+
requestId
|
|
3111
|
+
});
|
|
3112
|
+
}
|
|
3113
|
+
async deleteJob(jobName, token, requestId) {
|
|
3114
|
+
if (!jobName?.trim()) {
|
|
3115
|
+
throw new Error("Job name is required");
|
|
3116
|
+
}
|
|
3117
|
+
return this.requestService.delete({
|
|
3118
|
+
url: this.jobUrl(jobName),
|
|
3119
|
+
params: { "api-version": API_VERSION },
|
|
3120
|
+
eventName: jobEventNames_1.JobApiEvents.DELETE_JOB,
|
|
3121
|
+
token,
|
|
3122
|
+
requestId
|
|
3123
|
+
});
|
|
3124
|
+
}
|
|
3125
|
+
async disableJob(jobName, token, requestId) {
|
|
3126
|
+
if (!jobName?.trim()) {
|
|
3127
|
+
throw new Error("Job name is required");
|
|
3128
|
+
}
|
|
3129
|
+
const current = await this.getJob(jobName, token, requestId);
|
|
3130
|
+
const updated = { ...current, jobDefinition: { ...current.jobDefinition, isDisabled: true } };
|
|
3131
|
+
return this.requestService.put({
|
|
3132
|
+
url: this.jobUrl(jobName),
|
|
3133
|
+
params: { "api-version": API_VERSION },
|
|
3134
|
+
eventName: jobEventNames_1.JobApiEvents.DISABLE_JOB,
|
|
3135
|
+
body: JSON.stringify(updated),
|
|
3136
|
+
token,
|
|
3137
|
+
requestId
|
|
3138
|
+
});
|
|
3139
|
+
}
|
|
3140
|
+
async enableJob(jobName, token, requestId) {
|
|
3141
|
+
if (!jobName?.trim()) {
|
|
3142
|
+
throw new Error("Job name is required");
|
|
3143
|
+
}
|
|
3144
|
+
const current = await this.getJob(jobName, token, requestId);
|
|
3145
|
+
const updated = { ...current, jobDefinition: { ...current.jobDefinition, isDisabled: false } };
|
|
3146
|
+
return this.requestService.put({
|
|
3147
|
+
url: this.jobUrl(jobName),
|
|
3148
|
+
params: { "api-version": API_VERSION },
|
|
3149
|
+
eventName: jobEventNames_1.JobApiEvents.ENABLE_JOB,
|
|
3150
|
+
body: JSON.stringify(updated),
|
|
3151
|
+
token,
|
|
3152
|
+
requestId
|
|
3153
|
+
});
|
|
3154
|
+
}
|
|
3155
|
+
jobRunsUrl(jobName) {
|
|
3156
|
+
return `${this.jobUrl(jobName)}/runs`;
|
|
3157
|
+
}
|
|
3158
|
+
jobRunUrl(jobName, runId) {
|
|
3159
|
+
return `${this.jobRunsUrl(jobName)}/${encodeURIComponent(runId)}`;
|
|
3160
|
+
}
|
|
3161
|
+
async listJobRuns(jobName, token, requestId) {
|
|
3162
|
+
if (!jobName?.trim()) {
|
|
3163
|
+
throw new Error("Job name is required");
|
|
3164
|
+
}
|
|
3165
|
+
const runs = [];
|
|
3166
|
+
let continuationToken = void 0;
|
|
3167
|
+
do {
|
|
3168
|
+
const params = { "api-version": API_VERSION };
|
|
3169
|
+
if (continuationToken !== null && continuationToken !== void 0) {
|
|
3170
|
+
params.continuationToken = continuationToken;
|
|
3171
|
+
}
|
|
3172
|
+
const data = await this.requestService.get({
|
|
3173
|
+
url: this.jobRunsUrl(jobName),
|
|
3174
|
+
params,
|
|
3175
|
+
eventName: jobEventNames_1.JobApiEvents.LIST_JOB_RUNS,
|
|
3176
|
+
token,
|
|
3177
|
+
requestId
|
|
3178
|
+
});
|
|
3179
|
+
if (data?.results) {
|
|
3180
|
+
runs.push(...data.results);
|
|
3181
|
+
}
|
|
3182
|
+
continuationToken = data?.continuationToken ?? null;
|
|
3183
|
+
} while (continuationToken !== null);
|
|
3184
|
+
return runs;
|
|
3185
|
+
}
|
|
3186
|
+
async getJobRun(jobName, runId, token, requestId) {
|
|
3187
|
+
if (!jobName?.trim()) {
|
|
3188
|
+
throw new Error("Job name is required");
|
|
3189
|
+
}
|
|
3190
|
+
if (!runId?.trim()) {
|
|
3191
|
+
throw new Error("Run ID is required");
|
|
3192
|
+
}
|
|
3193
|
+
return this.requestService.get({
|
|
3194
|
+
url: this.jobRunUrl(jobName, runId),
|
|
3195
|
+
params: { "api-version": API_VERSION },
|
|
3196
|
+
eventName: jobEventNames_1.JobApiEvents.GET_JOB_RUN,
|
|
3197
|
+
token,
|
|
3198
|
+
requestId
|
|
3199
|
+
});
|
|
3200
|
+
}
|
|
3201
|
+
async startJobRun(jobName, token, requestId) {
|
|
3202
|
+
if (!jobName?.trim()) {
|
|
3203
|
+
throw new Error("Job name is required");
|
|
3204
|
+
}
|
|
3205
|
+
return this.requestService.post({
|
|
3206
|
+
url: `${this.jobUrl(jobName)}:runNow`,
|
|
3207
|
+
params: { "api-version": API_VERSION },
|
|
3208
|
+
eventName: jobEventNames_1.JobApiEvents.START_JOB_RUN,
|
|
3209
|
+
body: JSON.stringify({}),
|
|
3210
|
+
token,
|
|
3211
|
+
requestId
|
|
3212
|
+
});
|
|
3213
|
+
}
|
|
3214
|
+
async cancelJobRun(jobName, runId, token, requestId) {
|
|
3215
|
+
if (!jobName?.trim()) {
|
|
3216
|
+
throw new Error("Job name is required");
|
|
3217
|
+
}
|
|
3218
|
+
if (!runId?.trim()) {
|
|
3219
|
+
throw new Error("Run ID is required");
|
|
3220
|
+
}
|
|
3221
|
+
return this.requestService.post({
|
|
3222
|
+
url: `${this.jobRunUrl(jobName, runId)}:cancel`,
|
|
3223
|
+
params: { "api-version": API_VERSION },
|
|
3224
|
+
eventName: jobEventNames_1.JobApiEvents.CANCEL_JOB_RUN,
|
|
3225
|
+
body: JSON.stringify({}),
|
|
3226
|
+
token,
|
|
3227
|
+
requestId
|
|
3228
|
+
});
|
|
3229
|
+
}
|
|
3230
|
+
async listJobs(token, requestId) {
|
|
3231
|
+
const jobs = [];
|
|
3232
|
+
let continuationToken = void 0;
|
|
3233
|
+
do {
|
|
3234
|
+
const params = { jobType: sentinel_graph_job_1.JobType.Notebook, "api-version": API_VERSION };
|
|
3235
|
+
if (continuationToken !== null && continuationToken !== void 0) {
|
|
3236
|
+
params.continuationToken = continuationToken;
|
|
3237
|
+
}
|
|
3238
|
+
const data = await this.requestService.get({
|
|
3239
|
+
url: this.jobsUrl,
|
|
3240
|
+
params,
|
|
3241
|
+
eventName: jobEventNames_1.JobApiEvents.LOAD_JOBS,
|
|
3242
|
+
token,
|
|
3243
|
+
requestId
|
|
3244
|
+
});
|
|
3245
|
+
if (data?.results) {
|
|
3246
|
+
const pageJobs = data.results.map((result) => {
|
|
3247
|
+
if (!result.jobDefinition.jobName) {
|
|
3248
|
+
return null;
|
|
3249
|
+
}
|
|
3250
|
+
return {
|
|
3251
|
+
jobName: result.jobDefinition.jobName,
|
|
3252
|
+
id: result.jobDefinition.jobDefinitionId,
|
|
3253
|
+
isDisabled: result.jobDefinition.isDisabled,
|
|
3254
|
+
jobType: result.jobDefinition.jobType
|
|
3255
|
+
};
|
|
3256
|
+
}).filter((job) => job !== null);
|
|
3257
|
+
jobs.push(...pageJobs);
|
|
3258
|
+
}
|
|
3259
|
+
continuationToken = data?.continuationToken ?? null;
|
|
3260
|
+
} while (continuationToken !== null);
|
|
3261
|
+
return jobs;
|
|
3262
|
+
}
|
|
3263
|
+
};
|
|
3264
|
+
exports2.JobApiClient = JobApiClient2;
|
|
3265
|
+
}
|
|
3266
|
+
});
|
|
3267
|
+
|
|
3268
|
+
// ../../packages/common/dist/src/services/jobs/index.js
|
|
3269
|
+
var require_jobs2 = __commonJS({
|
|
3270
|
+
"../../packages/common/dist/src/services/jobs/index.js"(exports2) {
|
|
3271
|
+
"use strict";
|
|
3272
|
+
init_cjs_shims();
|
|
3273
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3274
|
+
exports2.JobApiClient = void 0;
|
|
3275
|
+
var jobApiClient_1 = require_jobApiClient();
|
|
3276
|
+
Object.defineProperty(exports2, "JobApiClient", { enumerable: true, get: function() {
|
|
3277
|
+
return jobApiClient_1.JobApiClient;
|
|
3278
|
+
} });
|
|
3279
|
+
}
|
|
3280
|
+
});
|
|
3281
|
+
|
|
3282
|
+
// ../../packages/common/dist/src/services/lake/lakeApiClient.js
|
|
3283
|
+
var require_lakeApiClient = __commonJS({
|
|
3284
|
+
"../../packages/common/dist/src/services/lake/lakeApiClient.js"(exports2) {
|
|
3285
|
+
"use strict";
|
|
3286
|
+
init_cjs_shims();
|
|
3287
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3288
|
+
exports2.LakeApiClient = void 0;
|
|
3289
|
+
exports2.isFederatedTable = isFederatedTable;
|
|
3290
|
+
exports2.getFederatedDatasourceKind = getFederatedDatasourceKind;
|
|
3291
|
+
var lakeEventNames_1 = require_lakeEventNames();
|
|
3292
|
+
var FEDERATED_TABLE_TYPE = "Federated";
|
|
3293
|
+
function isFederatedTable(table) {
|
|
3294
|
+
return table.tableType === FEDERATED_TABLE_TYPE;
|
|
3295
|
+
}
|
|
3296
|
+
function getFederatedDatasourceKind(table) {
|
|
3297
|
+
return table.fabricDetails?.federationDetails?.federatedDatasourceKind;
|
|
3298
|
+
}
|
|
3299
|
+
var API_VERSION = {
|
|
3300
|
+
DATABASES_API_VERSION: "2024-07-01",
|
|
3301
|
+
TABLES_API_VERSION: "2024-05-01-preview"
|
|
3302
|
+
};
|
|
3303
|
+
var LAKE_PATHS = {
|
|
3304
|
+
TABLES: "/lake/tables",
|
|
3305
|
+
DATABASES: "/lake/databases"
|
|
3306
|
+
};
|
|
3307
|
+
var LakeApiClient2 = class {
|
|
3308
|
+
requestService;
|
|
3309
|
+
telemetry;
|
|
3310
|
+
baseUrl;
|
|
3311
|
+
constructor(options) {
|
|
3312
|
+
this.requestService = options.requestService;
|
|
3313
|
+
this.telemetry = options.telemetry;
|
|
3314
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
3315
|
+
}
|
|
3316
|
+
get tablesUrl() {
|
|
3317
|
+
return `${this.baseUrl}${LAKE_PATHS.TABLES}`;
|
|
3318
|
+
}
|
|
3319
|
+
get databasesUrl() {
|
|
3320
|
+
return `${this.baseUrl}${LAKE_PATHS.DATABASES}`;
|
|
3321
|
+
}
|
|
3322
|
+
/**
|
|
3323
|
+
* Fetches all lake tables. If a database is specified, fetches tables for that database only.
|
|
3324
|
+
*/
|
|
3325
|
+
async fetchLakeTables(accessToken, clientRequestId, database) {
|
|
3326
|
+
const span = this.telemetry.span(lakeEventNames_1.LakeApiEvents.LOAD_TABLES, { requestId: clientRequestId ?? "" });
|
|
3327
|
+
try {
|
|
3328
|
+
let url = this.tablesUrl;
|
|
3329
|
+
let params = database ? { databaseName: database.databaseName } : void 0;
|
|
3330
|
+
const tables = [];
|
|
3331
|
+
do {
|
|
3332
|
+
const response = await this.fetchTables(url, accessToken, clientRequestId, params);
|
|
3333
|
+
tables.push(...response.items);
|
|
3334
|
+
url = response.nextLink || null;
|
|
3335
|
+
params = void 0;
|
|
3336
|
+
} while (url);
|
|
3337
|
+
return tables;
|
|
3338
|
+
} finally {
|
|
3339
|
+
span.end();
|
|
3340
|
+
}
|
|
3341
|
+
}
|
|
3342
|
+
async fetchDatabases(accessToken, clientRequestId) {
|
|
3343
|
+
const data = await this.requestService.get({
|
|
3344
|
+
url: this.databasesUrl,
|
|
3345
|
+
params: { "api-version": API_VERSION.DATABASES_API_VERSION },
|
|
3346
|
+
eventName: lakeEventNames_1.LakeApiEvents.LOAD_DATABASES,
|
|
3347
|
+
token: accessToken,
|
|
3348
|
+
requestId: clientRequestId
|
|
3349
|
+
});
|
|
3350
|
+
return data.value;
|
|
3351
|
+
}
|
|
3352
|
+
async fetchTables(url, accessToken, clientRequestId, params) {
|
|
3353
|
+
return this.requestService.get({
|
|
3354
|
+
url,
|
|
3355
|
+
params: {
|
|
3356
|
+
"api-version": API_VERSION.TABLES_API_VERSION,
|
|
3357
|
+
...params
|
|
3358
|
+
},
|
|
3359
|
+
eventName: lakeEventNames_1.LakeApiEvents.LOAD_TABLES,
|
|
3360
|
+
token: accessToken,
|
|
3361
|
+
requestId: clientRequestId
|
|
3362
|
+
});
|
|
3363
|
+
}
|
|
3364
|
+
};
|
|
3365
|
+
exports2.LakeApiClient = LakeApiClient2;
|
|
3366
|
+
}
|
|
3367
|
+
});
|
|
3368
|
+
|
|
3369
|
+
// ../../packages/common/dist/src/services/lake/index.js
|
|
3370
|
+
var require_lake2 = __commonJS({
|
|
3371
|
+
"../../packages/common/dist/src/services/lake/index.js"(exports2) {
|
|
3372
|
+
"use strict";
|
|
3373
|
+
init_cjs_shims();
|
|
3374
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3375
|
+
exports2.getFederatedDatasourceKind = exports2.isFederatedTable = exports2.LakeApiClient = void 0;
|
|
3376
|
+
var lakeApiClient_1 = require_lakeApiClient();
|
|
3377
|
+
Object.defineProperty(exports2, "LakeApiClient", { enumerable: true, get: function() {
|
|
3378
|
+
return lakeApiClient_1.LakeApiClient;
|
|
3379
|
+
} });
|
|
3380
|
+
Object.defineProperty(exports2, "isFederatedTable", { enumerable: true, get: function() {
|
|
3381
|
+
return lakeApiClient_1.isFederatedTable;
|
|
3382
|
+
} });
|
|
3383
|
+
Object.defineProperty(exports2, "getFederatedDatasourceKind", { enumerable: true, get: function() {
|
|
3384
|
+
return lakeApiClient_1.getFederatedDatasourceKind;
|
|
3385
|
+
} });
|
|
3386
|
+
}
|
|
3387
|
+
});
|
|
3388
|
+
|
|
2847
3389
|
// ../../packages/common/dist/src/services/httpService.js
|
|
2848
3390
|
var require_httpService = __commonJS({
|
|
2849
3391
|
"../../packages/common/dist/src/services/httpService.js"(exports2) {
|
|
@@ -2855,7 +3397,7 @@ var require_httpService = __commonJS({
|
|
|
2855
3397
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2856
3398
|
exports2.HttpService = void 0;
|
|
2857
3399
|
var axios_1 = __importDefault(require("axios"));
|
|
2858
|
-
var
|
|
3400
|
+
var HttpService = class {
|
|
2859
3401
|
httpInstance;
|
|
2860
3402
|
// Implement the interface
|
|
2861
3403
|
constructor(httpInstance) {
|
|
@@ -2920,7 +3462,7 @@ var require_httpService = __commonJS({
|
|
|
2920
3462
|
}
|
|
2921
3463
|
}
|
|
2922
3464
|
};
|
|
2923
|
-
exports2.HttpService =
|
|
3465
|
+
exports2.HttpService = HttpService;
|
|
2924
3466
|
}
|
|
2925
3467
|
});
|
|
2926
3468
|
|
|
@@ -2933,81 +3475,6 @@ var require_httpServiceInterface = __commonJS({
|
|
|
2933
3475
|
}
|
|
2934
3476
|
});
|
|
2935
3477
|
|
|
2936
|
-
// ../../packages/common/dist/src/services/jobService.js
|
|
2937
|
-
var require_jobService = __commonJS({
|
|
2938
|
-
"../../packages/common/dist/src/services/jobService.js"(exports2) {
|
|
2939
|
-
"use strict";
|
|
2940
|
-
init_cjs_shims();
|
|
2941
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2942
|
-
exports2.JobService = void 0;
|
|
2943
|
-
var JobService2 = class {
|
|
2944
|
-
env;
|
|
2945
|
-
region;
|
|
2946
|
-
httpInstance;
|
|
2947
|
-
API_VERSION = "2023-09-30-preview";
|
|
2948
|
-
constructor(env, region, httpInstance) {
|
|
2949
|
-
this.env = env;
|
|
2950
|
-
this.region = region;
|
|
2951
|
-
this.httpInstance = httpInstance;
|
|
2952
|
-
if (!env || !region) {
|
|
2953
|
-
throw new Error("Environment and region must be provided.");
|
|
2954
|
-
}
|
|
2955
|
-
if (!env.regions[region]) {
|
|
2956
|
-
throw new Error(`Region ${region} is not configured.`);
|
|
2957
|
-
}
|
|
2958
|
-
if (!httpInstance) {
|
|
2959
|
-
throw new Error("HTTP service instance must be provided.");
|
|
2960
|
-
}
|
|
2961
|
-
this.httpInstance = httpInstance;
|
|
2962
|
-
}
|
|
2963
|
-
async getHttpInstance() {
|
|
2964
|
-
return this.httpInstance;
|
|
2965
|
-
}
|
|
2966
|
-
getBaseUrl() {
|
|
2967
|
-
const regionConfig = this.env.regions[this.region];
|
|
2968
|
-
return regionConfig.gatewayEndpoint;
|
|
2969
|
-
}
|
|
2970
|
-
async createJob(jobName, payload) {
|
|
2971
|
-
if (!jobName?.trim()) {
|
|
2972
|
-
throw new Error("Job name is required");
|
|
2973
|
-
}
|
|
2974
|
-
const httpInstance = await this.getHttpInstance();
|
|
2975
|
-
const url = `${this.getBaseUrl()}jobs/${encodeURIComponent(jobName)}?api-version=${this.API_VERSION}`;
|
|
2976
|
-
const { data } = await httpInstance.put(url, payload);
|
|
2977
|
-
return data;
|
|
2978
|
-
}
|
|
2979
|
-
async getJob(jobName) {
|
|
2980
|
-
if (!jobName?.trim()) {
|
|
2981
|
-
throw new Error("Job name is required");
|
|
2982
|
-
}
|
|
2983
|
-
const httpInstance = await this.getHttpInstance();
|
|
2984
|
-
const url = `${this.getBaseUrl()}jobs/${encodeURIComponent(jobName)}?api-version=${this.API_VERSION}`;
|
|
2985
|
-
const { data } = await httpInstance.get(url);
|
|
2986
|
-
return data;
|
|
2987
|
-
}
|
|
2988
|
-
async deleteJob(jobName) {
|
|
2989
|
-
if (!jobName?.trim()) {
|
|
2990
|
-
throw new Error("Job name is required");
|
|
2991
|
-
}
|
|
2992
|
-
const httpInstance = await this.getHttpInstance();
|
|
2993
|
-
const url = `${this.getBaseUrl()}jobs/${encodeURIComponent(jobName)}?api-version=${this.API_VERSION}`;
|
|
2994
|
-
const { data } = await httpInstance.delete(url);
|
|
2995
|
-
return data;
|
|
2996
|
-
}
|
|
2997
|
-
};
|
|
2998
|
-
exports2.JobService = JobService2;
|
|
2999
|
-
}
|
|
3000
|
-
});
|
|
3001
|
-
|
|
3002
|
-
// ../../packages/common/dist/src/services/jobServiceInterface.js
|
|
3003
|
-
var require_jobServiceInterface = __commonJS({
|
|
3004
|
-
"../../packages/common/dist/src/services/jobServiceInterface.js"(exports2) {
|
|
3005
|
-
"use strict";
|
|
3006
|
-
init_cjs_shims();
|
|
3007
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3008
|
-
}
|
|
3009
|
-
});
|
|
3010
|
-
|
|
3011
3478
|
// ../../node_modules/.pnpm/js-yaml@4.1.1/node_modules/js-yaml/lib/common.js
|
|
3012
3479
|
var require_common2 = __commonJS({
|
|
3013
3480
|
"../../node_modules/.pnpm/js-yaml@4.1.1/node_modules/js-yaml/lib/common.js"(exports2, module2) {
|
|
@@ -3016,7 +3483,7 @@ var require_common2 = __commonJS({
|
|
|
3016
3483
|
function isNothing(subject) {
|
|
3017
3484
|
return typeof subject === "undefined" || subject === null;
|
|
3018
3485
|
}
|
|
3019
|
-
function
|
|
3486
|
+
function isObject2(subject) {
|
|
3020
3487
|
return typeof subject === "object" && subject !== null;
|
|
3021
3488
|
}
|
|
3022
3489
|
function toArray(sequence) {
|
|
@@ -3046,7 +3513,7 @@ var require_common2 = __commonJS({
|
|
|
3046
3513
|
return number === 0 && Number.NEGATIVE_INFINITY === 1 / number;
|
|
3047
3514
|
}
|
|
3048
3515
|
module2.exports.isNothing = isNothing;
|
|
3049
|
-
module2.exports.isObject =
|
|
3516
|
+
module2.exports.isObject = isObject2;
|
|
3050
3517
|
module2.exports.toArray = toArray;
|
|
3051
3518
|
module2.exports.repeat = repeat;
|
|
3052
3519
|
module2.exports.isNegativeZero = isNegativeZero;
|
|
@@ -5874,10 +6341,10 @@ var require_notebookUtils = __commonJS({
|
|
|
5874
6341
|
exports2.getJupyterNotebook = getJupyterNotebook;
|
|
5875
6342
|
exports2.removeCellOutput = removeCellOutput;
|
|
5876
6343
|
exports2.notebookToBase64 = notebookToBase64;
|
|
5877
|
-
var
|
|
6344
|
+
var fs7 = __importStar(require("fs/promises"));
|
|
5878
6345
|
async function getJupyterNotebook(filePath) {
|
|
5879
6346
|
try {
|
|
5880
|
-
const notebookFile = await
|
|
6347
|
+
const notebookFile = await fs7.readFile(filePath, "utf-8");
|
|
5881
6348
|
return JSON.parse(notebookFile);
|
|
5882
6349
|
} catch (error) {
|
|
5883
6350
|
throw new Error(`Failed to read or parse the notebook file: ${error}`);
|
|
@@ -5955,18 +6422,18 @@ var require_secureExchangeManifestUtils = __commonJS({
|
|
|
5955
6422
|
})();
|
|
5956
6423
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
5957
6424
|
exports2.updateSecureExchangeManifest = updateSecureExchangeManifest;
|
|
5958
|
-
var
|
|
6425
|
+
var fs7 = __importStar(require("fs-extra"));
|
|
5959
6426
|
var yaml = __importStar(require("yaml"));
|
|
5960
6427
|
async function updateSecureExchangeManifest(manifestEntries, secureExchangeManifestPath) {
|
|
5961
6428
|
if (manifestEntries.length > 0) {
|
|
5962
|
-
const existingYaml = await
|
|
6429
|
+
const existingYaml = await fs7.readFile(secureExchangeManifestPath, "utf-8");
|
|
5963
6430
|
const parsedYaml = existingYaml ? yaml.parse(existingYaml) || [] : [];
|
|
5964
6431
|
const newEntries = manifestEntries.filter((newEntry) => !parsedYaml.some((existingEntry) => existingEntry.id === newEntry.id && existingEntry.type === newEntry.type));
|
|
5965
6432
|
if (newEntries.length === 0) {
|
|
5966
6433
|
return;
|
|
5967
6434
|
}
|
|
5968
6435
|
const updatedYaml = [...parsedYaml, ...newEntries];
|
|
5969
|
-
await
|
|
6436
|
+
await fs7.writeFile(secureExchangeManifestPath, yaml.stringify(updatedYaml), "utf-8");
|
|
5970
6437
|
}
|
|
5971
6438
|
}
|
|
5972
6439
|
}
|
|
@@ -6582,8 +7049,8 @@ var require_zipDirectory = __commonJS({
|
|
|
6582
7049
|
try {
|
|
6583
7050
|
const output = fs_1.default.createWriteStream(outPath);
|
|
6584
7051
|
const archive = (0, archiver_1.default)("zip", { zlib: { level: 9 } });
|
|
6585
|
-
return new Promise((
|
|
6586
|
-
output.on("close",
|
|
7052
|
+
return new Promise((resolve2, reject) => {
|
|
7053
|
+
output.on("close", resolve2);
|
|
6587
7054
|
output.on("error", reject);
|
|
6588
7055
|
archive.on("error", reject);
|
|
6589
7056
|
archive.pipe(output);
|
|
@@ -6660,8 +7127,8 @@ var require_manifestProcessorService = __commonJS({
|
|
|
6660
7127
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
6661
7128
|
exports2.ManifestProcessorService = void 0;
|
|
6662
7129
|
var crypto_1 = require("crypto");
|
|
6663
|
-
var
|
|
6664
|
-
var
|
|
7130
|
+
var fs7 = __importStar(require("fs-extra"));
|
|
7131
|
+
var path8 = __importStar(require("path"));
|
|
6665
7132
|
var yaml = __importStar(require("yaml"));
|
|
6666
7133
|
var constants_1 = require_constants();
|
|
6667
7134
|
var buildScheduledJobArtifacts_1 = require_buildScheduledJobArtifacts();
|
|
@@ -6684,17 +7151,17 @@ var require_manifestProcessorService = __commonJS({
|
|
|
6684
7151
|
};
|
|
6685
7152
|
}
|
|
6686
7153
|
async buildZipPackage(manifestPath) {
|
|
6687
|
-
const manifestDir =
|
|
6688
|
-
const tempPackageDir =
|
|
7154
|
+
const manifestDir = path8.dirname(path8.resolve(manifestPath));
|
|
7155
|
+
const tempPackageDir = path8.join(manifestDir, ".packaging-temp");
|
|
6689
7156
|
try {
|
|
6690
|
-
await
|
|
6691
|
-
await
|
|
7157
|
+
await fs7.rm(tempPackageDir, { recursive: true, force: true });
|
|
7158
|
+
await fs7.mkdir(tempPackageDir, { recursive: true });
|
|
6692
7159
|
const manifest = await (0, manifestParser_1.parseManifest)(manifestPath);
|
|
6693
|
-
const discoveredFiles = await (0, discoverFiles_1.discoverFiles)(manifest.includePaths,
|
|
7160
|
+
const discoveredFiles = await (0, discoverFiles_1.discoverFiles)(manifest.includePaths, path8.dirname(path8.resolve(manifestPath)));
|
|
6694
7161
|
console.log("Discovered files:", JSON.stringify(discoveredFiles, null, 2));
|
|
6695
7162
|
(0, manifestValidator_1.validateSingleScAgent)(discoveredFiles);
|
|
6696
|
-
const secureExchangeManifestPath =
|
|
6697
|
-
await
|
|
7163
|
+
const secureExchangeManifestPath = path8.join(tempPackageDir, "PackageManifest.yaml");
|
|
7164
|
+
await fs7.writeFile(secureExchangeManifestPath, "");
|
|
6698
7165
|
console.log("Empty PackageManifest.yaml created at:", secureExchangeManifestPath);
|
|
6699
7166
|
await (0, processMainTemplate_1.processMainTemplate)(discoveredFiles, tempPackageDir, secureExchangeManifestPath);
|
|
6700
7167
|
console.log("mainTemplate.json processed and added to PackageManifest.yaml");
|
|
@@ -6704,8 +7171,8 @@ var require_manifestProcessorService = __commonJS({
|
|
|
6704
7171
|
console.log("SC Agents processed and PackageManifest.yaml updated.");
|
|
6705
7172
|
await (0, refactorManifest_1.finalizeManifest)(secureExchangeManifestPath, tempPackageDir);
|
|
6706
7173
|
const zipName = `${manifest.packageName}.zip`;
|
|
6707
|
-
const manifestDir2 =
|
|
6708
|
-
const outputZipPath =
|
|
7174
|
+
const manifestDir2 = path8.dirname(path8.resolve(manifestPath));
|
|
7175
|
+
const outputZipPath = path8.join(manifestDir2, zipName);
|
|
6709
7176
|
await (0, zipDirectory_1.zipDirectory)(tempPackageDir, outputZipPath);
|
|
6710
7177
|
console.log("Package zipped at:", outputZipPath);
|
|
6711
7178
|
return outputZipPath;
|
|
@@ -6717,21 +7184,21 @@ var require_manifestProcessorService = __commonJS({
|
|
|
6717
7184
|
}
|
|
6718
7185
|
} finally {
|
|
6719
7186
|
try {
|
|
6720
|
-
await
|
|
7187
|
+
await fs7.rm(tempPackageDir, { recursive: true, force: true });
|
|
6721
7188
|
} catch (err) {
|
|
6722
7189
|
console.warn("Please clean the temp directory as Failed to clean up temp directory:", err);
|
|
6723
7190
|
}
|
|
6724
7191
|
}
|
|
6725
7192
|
}
|
|
6726
7193
|
async validateManifest(manifestPath) {
|
|
6727
|
-
const manifestDir =
|
|
6728
|
-
const tempPackageDir =
|
|
7194
|
+
const manifestDir = path8.dirname(path8.resolve(manifestPath));
|
|
7195
|
+
const tempPackageDir = path8.join(manifestDir, ".packaging-temp");
|
|
6729
7196
|
let parsed;
|
|
6730
7197
|
try {
|
|
6731
|
-
await
|
|
6732
|
-
const content = await
|
|
7198
|
+
await fs7.rm(tempPackageDir, { recursive: true, force: true });
|
|
7199
|
+
const content = await fs7.readFile(manifestPath, "utf8");
|
|
6733
7200
|
parsed = yaml.parse(content);
|
|
6734
|
-
const discoveredFiles = await (0, discoverFiles_1.discoverFiles)(parsed.includePaths,
|
|
7201
|
+
const discoveredFiles = await (0, discoverFiles_1.discoverFiles)(parsed.includePaths, path8.dirname(path8.resolve(manifestPath)));
|
|
6735
7202
|
(0, manifestValidator_1.validateSingleScAgent)(discoveredFiles);
|
|
6736
7203
|
const yamlType = parsed.yamlType;
|
|
6737
7204
|
if (!yamlType) {
|
|
@@ -6741,8 +7208,8 @@ var require_manifestProcessorService = __commonJS({
|
|
|
6741
7208
|
if (!validator) {
|
|
6742
7209
|
throw new Error(`No validator found for yamlType '${yamlType}'`);
|
|
6743
7210
|
}
|
|
6744
|
-
const absPath =
|
|
6745
|
-
const manifestDir2 =
|
|
7211
|
+
const absPath = path8.resolve(manifestPath);
|
|
7212
|
+
const manifestDir2 = path8.dirname(absPath);
|
|
6746
7213
|
await validator(parsed, manifestDir2);
|
|
6747
7214
|
} catch (err) {
|
|
6748
7215
|
if (err instanceof Error) {
|
|
@@ -6752,30 +7219,30 @@ var require_manifestProcessorService = __commonJS({
|
|
|
6752
7219
|
}
|
|
6753
7220
|
} finally {
|
|
6754
7221
|
try {
|
|
6755
|
-
await
|
|
7222
|
+
await fs7.rm(tempPackageDir, { recursive: true, force: true });
|
|
6756
7223
|
} catch (err) {
|
|
6757
7224
|
console.warn("Please clean the temp directory as Failed to clean up temp directory:", err);
|
|
6758
7225
|
}
|
|
6759
7226
|
}
|
|
6760
7227
|
}
|
|
6761
7228
|
async buildSideLoadRequest(manifestPath) {
|
|
6762
|
-
const manifestDir =
|
|
6763
|
-
const tempPackageDir =
|
|
6764
|
-
const sentinelLakeDir =
|
|
7229
|
+
const manifestDir = path8.dirname(path8.resolve(manifestPath));
|
|
7230
|
+
const tempPackageDir = path8.join(manifestDir, ".packaging-temp");
|
|
7231
|
+
const sentinelLakeDir = path8.join(tempPackageDir, constants_1.PackageManifestIdValues.SentinelLakeId);
|
|
6765
7232
|
const deploymentId = (0, crypto_1.randomUUID)();
|
|
6766
7233
|
try {
|
|
6767
|
-
await
|
|
7234
|
+
await fs7.rm(tempPackageDir, { recursive: true, force: true });
|
|
6768
7235
|
const manifest = await (0, manifestParser_1.parseManifest)(manifestPath);
|
|
6769
|
-
const discoveredFiles = await (0, discoverFiles_1.discoverFiles)(manifest.includePaths,
|
|
7236
|
+
const discoveredFiles = await (0, discoverFiles_1.discoverFiles)(manifest.includePaths, path8.dirname(path8.resolve(manifestPath)));
|
|
6770
7237
|
console.log("Discovered files:", JSON.stringify(discoveredFiles, null, 2));
|
|
6771
|
-
await
|
|
7238
|
+
await fs7.mkdir(tempPackageDir, { recursive: true });
|
|
6772
7239
|
await (0, buildScheduledJobArtifacts_1.processScheduledJobs)(discoveredFiles, tempPackageDir, "");
|
|
6773
|
-
const jobDirs = await
|
|
7240
|
+
const jobDirs = await fs7.readdir(sentinelLakeDir);
|
|
6774
7241
|
const artifacts = [];
|
|
6775
7242
|
for (const dir of jobDirs) {
|
|
6776
|
-
const deploymentJsonPath =
|
|
6777
|
-
if (await
|
|
6778
|
-
const jsonContent = await
|
|
7243
|
+
const deploymentJsonPath = path8.join(sentinelLakeDir, dir, "deployment.json");
|
|
7244
|
+
if (await fs7.pathExists(deploymentJsonPath)) {
|
|
7245
|
+
const jsonContent = await fs7.readFile(deploymentJsonPath, "utf8");
|
|
6779
7246
|
const escapedJson = JSON.stringify(JSON.parse(jsonContent));
|
|
6780
7247
|
artifacts.push({
|
|
6781
7248
|
name: "deployment.yaml",
|
|
@@ -6798,7 +7265,7 @@ var require_manifestProcessorService = __commonJS({
|
|
|
6798
7265
|
console.error("Error building side-load request:", error);
|
|
6799
7266
|
throw error;
|
|
6800
7267
|
} finally {
|
|
6801
|
-
await
|
|
7268
|
+
await fs7.remove(tempPackageDir);
|
|
6802
7269
|
}
|
|
6803
7270
|
}
|
|
6804
7271
|
};
|
|
@@ -7052,14 +7519,15 @@ var require_services = __commonJS({
|
|
|
7052
7519
|
o[k2] = m[k];
|
|
7053
7520
|
}));
|
|
7054
7521
|
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
7055
|
-
for (var
|
|
7522
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
7056
7523
|
};
|
|
7057
7524
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7525
|
+
__exportStar(require_tenant(), exports2);
|
|
7058
7526
|
__exportStar(require_httpConstants(), exports2);
|
|
7527
|
+
__exportStar(require_jobs2(), exports2);
|
|
7528
|
+
__exportStar(require_lake2(), exports2);
|
|
7059
7529
|
__exportStar(require_httpService(), exports2);
|
|
7060
7530
|
__exportStar(require_httpServiceInterface(), exports2);
|
|
7061
|
-
__exportStar(require_jobService(), exports2);
|
|
7062
|
-
__exportStar(require_jobServiceInterface(), exports2);
|
|
7063
7531
|
__exportStar(require_manifestProcessorService(), exports2);
|
|
7064
7532
|
__exportStar(require_manifestProcessorServiceInterface(), exports2);
|
|
7065
7533
|
__exportStar(require_packageService(), exports2);
|
|
@@ -7086,26 +7554,122 @@ var require_errors = __commonJS({
|
|
|
7086
7554
|
o[k2] = m[k];
|
|
7087
7555
|
}));
|
|
7088
7556
|
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
7089
|
-
for (var
|
|
7557
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
7090
7558
|
};
|
|
7091
7559
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7092
7560
|
__exportStar(require_errorTypes(), exports2);
|
|
7093
7561
|
}
|
|
7094
7562
|
});
|
|
7095
7563
|
|
|
7096
|
-
// ../../packages/common/dist/src/
|
|
7097
|
-
var
|
|
7098
|
-
"../../packages/common/dist/src/
|
|
7564
|
+
// ../../packages/common/dist/src/telemetry/types.js
|
|
7565
|
+
var require_types2 = __commonJS({
|
|
7566
|
+
"../../packages/common/dist/src/telemetry/types.js"(exports2) {
|
|
7099
7567
|
"use strict";
|
|
7100
7568
|
init_cjs_shims();
|
|
7101
|
-
|
|
7102
|
-
|
|
7569
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7570
|
+
}
|
|
7571
|
+
});
|
|
7572
|
+
|
|
7573
|
+
// ../../packages/common/dist/src/telemetry/index.js
|
|
7574
|
+
var require_telemetry = __commonJS({
|
|
7575
|
+
"../../packages/common/dist/src/telemetry/index.js"(exports2) {
|
|
7576
|
+
"use strict";
|
|
7577
|
+
init_cjs_shims();
|
|
7578
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
7579
|
+
if (k2 === void 0) k2 = k;
|
|
7580
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7581
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7582
|
+
desc = { enumerable: true, get: function() {
|
|
7583
|
+
return m[k];
|
|
7584
|
+
} };
|
|
7585
|
+
}
|
|
7586
|
+
Object.defineProperty(o, k2, desc);
|
|
7587
|
+
}) : (function(o, m, k, k2) {
|
|
7588
|
+
if (k2 === void 0) k2 = k;
|
|
7589
|
+
o[k2] = m[k];
|
|
7590
|
+
}));
|
|
7591
|
+
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
7592
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
7593
|
+
};
|
|
7594
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7595
|
+
__exportStar(require_types2(), exports2);
|
|
7596
|
+
}
|
|
7597
|
+
});
|
|
7598
|
+
|
|
7599
|
+
// ../../packages/common/dist/src/utils/decodeBase64Notebook.js
|
|
7600
|
+
var require_decodeBase64Notebook = __commonJS({
|
|
7601
|
+
"../../packages/common/dist/src/utils/decodeBase64Notebook.js"(exports2) {
|
|
7602
|
+
"use strict";
|
|
7603
|
+
init_cjs_shims();
|
|
7604
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7605
|
+
exports2.decodeBase64Notebook = decodeBase64Notebook3;
|
|
7606
|
+
var BASE64_RE = /^[A-Za-z0-9+/\r\n]*={0,2}$/;
|
|
7607
|
+
function decodeBase64Notebook3(encoded, label) {
|
|
7608
|
+
if (!encoded?.trim()) {
|
|
7609
|
+
throw new Error(`${label} has no notebook content to decode.`);
|
|
7610
|
+
}
|
|
7611
|
+
if (!BASE64_RE.test(encoded.trim())) {
|
|
7612
|
+
throw new Error(`${label} has an invalid base64-encoded notebook.`);
|
|
7613
|
+
}
|
|
7614
|
+
return Buffer.from(encoded, "base64").toString("utf-8");
|
|
7615
|
+
}
|
|
7616
|
+
}
|
|
7617
|
+
});
|
|
7618
|
+
|
|
7619
|
+
// ../../packages/common/dist/src/utils/pathUtils.js
|
|
7620
|
+
var require_pathUtils = __commonJS({
|
|
7621
|
+
"../../packages/common/dist/src/utils/pathUtils.js"(exports2) {
|
|
7622
|
+
"use strict";
|
|
7623
|
+
init_cjs_shims();
|
|
7624
|
+
var __importDefault = exports2 && exports2.__importDefault || function(mod) {
|
|
7625
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
7103
7626
|
};
|
|
7104
7627
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7105
7628
|
exports2.resolvePath = resolvePath2;
|
|
7106
7629
|
var path_1 = __importDefault(require("path"));
|
|
7107
|
-
function resolvePath2(
|
|
7108
|
-
return path_1.default.resolve(
|
|
7630
|
+
function resolvePath2(p4) {
|
|
7631
|
+
return path_1.default.resolve(p4);
|
|
7632
|
+
}
|
|
7633
|
+
}
|
|
7634
|
+
});
|
|
7635
|
+
|
|
7636
|
+
// ../../packages/common/dist/src/utils/tokenUtils.js
|
|
7637
|
+
var require_tokenUtils = __commonJS({
|
|
7638
|
+
"../../packages/common/dist/src/utils/tokenUtils.js"(exports2) {
|
|
7639
|
+
"use strict";
|
|
7640
|
+
init_cjs_shims();
|
|
7641
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7642
|
+
exports2.extractTenantId = extractTenantId2;
|
|
7643
|
+
var TOKEN_PARSING = {
|
|
7644
|
+
SEPARATOR: ".",
|
|
7645
|
+
BASE64_HYPHEN_REPLACEMENT: "+",
|
|
7646
|
+
BASE64_UNDERSCORE_REPLACEMENT: "/",
|
|
7647
|
+
BASE64_HYPHEN_PATTERN: /-/g,
|
|
7648
|
+
BASE64_UNDERSCORE_PATTERN: /_/g,
|
|
7649
|
+
BASE64_ENCODING: "base64",
|
|
7650
|
+
TENANT_ID_CLAIM: "tid",
|
|
7651
|
+
TOKEN_PARTS_LENGTH: 3,
|
|
7652
|
+
PAYLOAD_INDEX: 1
|
|
7653
|
+
};
|
|
7654
|
+
function extractTenantId2(accessToken) {
|
|
7655
|
+
try {
|
|
7656
|
+
const tokenParts = accessToken.split(TOKEN_PARSING.SEPARATOR);
|
|
7657
|
+
if (tokenParts.length !== TOKEN_PARSING.TOKEN_PARTS_LENGTH) {
|
|
7658
|
+
return void 0;
|
|
7659
|
+
}
|
|
7660
|
+
let base64Url = tokenParts[TOKEN_PARSING.PAYLOAD_INDEX].replace(TOKEN_PARSING.BASE64_HYPHEN_PATTERN, TOKEN_PARSING.BASE64_HYPHEN_REPLACEMENT).replace(TOKEN_PARSING.BASE64_UNDERSCORE_PATTERN, TOKEN_PARSING.BASE64_UNDERSCORE_REPLACEMENT);
|
|
7661
|
+
while (base64Url.length % 4 !== 0) {
|
|
7662
|
+
base64Url += "=";
|
|
7663
|
+
}
|
|
7664
|
+
const payload = JSON.parse(Buffer.from(base64Url, TOKEN_PARSING.BASE64_ENCODING).toString());
|
|
7665
|
+
if (typeof payload === "object" && payload !== null) {
|
|
7666
|
+
const tenantId = payload[TOKEN_PARSING.TENANT_ID_CLAIM];
|
|
7667
|
+
return typeof tenantId === "string" ? tenantId : void 0;
|
|
7668
|
+
}
|
|
7669
|
+
return void 0;
|
|
7670
|
+
} catch {
|
|
7671
|
+
return void 0;
|
|
7672
|
+
}
|
|
7109
7673
|
}
|
|
7110
7674
|
}
|
|
7111
7675
|
});
|
|
@@ -7129,12 +7693,14 @@ var require_utils = __commonJS({
|
|
|
7129
7693
|
o[k2] = m[k];
|
|
7130
7694
|
}));
|
|
7131
7695
|
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
7132
|
-
for (var
|
|
7696
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
7133
7697
|
};
|
|
7134
7698
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7135
7699
|
__exportStar(require_correlationService(), exports2);
|
|
7700
|
+
__exportStar(require_decodeBase64Notebook(), exports2);
|
|
7136
7701
|
__exportStar(require_pathUtils(), exports2);
|
|
7137
7702
|
__exportStar(require_jobPayloadUtils(), exports2);
|
|
7703
|
+
__exportStar(require_tokenUtils(), exports2);
|
|
7138
7704
|
}
|
|
7139
7705
|
});
|
|
7140
7706
|
|
|
@@ -7157,7 +7723,7 @@ var require_src = __commonJS({
|
|
|
7157
7723
|
o[k2] = m[k];
|
|
7158
7724
|
}));
|
|
7159
7725
|
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
7160
|
-
for (var
|
|
7726
|
+
for (var p4 in m) if (p4 !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p4)) __createBinding(exports3, m, p4);
|
|
7161
7727
|
};
|
|
7162
7728
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7163
7729
|
__exportStar(require_client(), exports2);
|
|
@@ -7167,6 +7733,7 @@ var require_src = __commonJS({
|
|
|
7167
7733
|
__exportStar(require_models(), exports2);
|
|
7168
7734
|
__exportStar(require_services(), exports2);
|
|
7169
7735
|
__exportStar(require_errors(), exports2);
|
|
7736
|
+
__exportStar(require_telemetry(), exports2);
|
|
7170
7737
|
__exportStar(require_utils(), exports2);
|
|
7171
7738
|
}
|
|
7172
7739
|
});
|
|
@@ -7210,352 +7777,2577 @@ function addCreateZipCommand(packageCommand) {
|
|
|
7210
7777
|
});
|
|
7211
7778
|
}
|
|
7212
7779
|
|
|
7213
|
-
// src/commands/
|
|
7780
|
+
// src/commands/jobs/jobDefinitionCreate.ts
|
|
7214
7781
|
init_cjs_shims();
|
|
7215
|
-
var os5 = __toESM(require("os"));
|
|
7216
7782
|
|
|
7217
|
-
// src/actions/
|
|
7783
|
+
// src/actions/jobs/index.ts
|
|
7784
|
+
init_cjs_shims();
|
|
7785
|
+
|
|
7786
|
+
// src/actions/jobs/listJobs.ts
|
|
7218
7787
|
init_cjs_shims();
|
|
7219
|
-
var import_child_process = require("child_process");
|
|
7220
7788
|
var import_common3 = __toESM(require_src());
|
|
7789
|
+
async function listJobs(jobService, accessToken) {
|
|
7790
|
+
const requestId = import_common3.CorrelationService.createCorrelationContext();
|
|
7791
|
+
console.info("Fetching jobs...");
|
|
7792
|
+
return jobService.listJobs(accessToken, requestId);
|
|
7793
|
+
}
|
|
7221
7794
|
|
|
7222
|
-
// src/
|
|
7795
|
+
// src/actions/jobs/getJob.ts
|
|
7223
7796
|
init_cjs_shims();
|
|
7224
|
-
var
|
|
7797
|
+
var import_common4 = __toESM(require_src());
|
|
7798
|
+
async function getJob(jobService, accessToken, jobName) {
|
|
7799
|
+
const requestId = import_common4.CorrelationService.createCorrelationContext();
|
|
7800
|
+
console.info(`Fetching job "${jobName}"...`);
|
|
7801
|
+
return jobService.getJob(jobName, accessToken, requestId);
|
|
7802
|
+
}
|
|
7225
7803
|
|
|
7226
|
-
// src/
|
|
7804
|
+
// src/actions/jobs/deleteJob.ts
|
|
7227
7805
|
init_cjs_shims();
|
|
7228
|
-
var
|
|
7229
|
-
|
|
7806
|
+
var import_common5 = __toESM(require_src());
|
|
7807
|
+
async function deleteJob(jobService, accessToken, jobName) {
|
|
7808
|
+
const requestId = import_common5.CorrelationService.createCorrelationContext();
|
|
7809
|
+
console.info(`Deleting job "${jobName}"...`);
|
|
7810
|
+
return jobService.deleteJob(jobName, accessToken, requestId);
|
|
7811
|
+
}
|
|
7230
7812
|
|
|
7231
|
-
// src/
|
|
7813
|
+
// src/actions/jobs/disableJob.ts
|
|
7232
7814
|
init_cjs_shims();
|
|
7233
|
-
var
|
|
7234
|
-
|
|
7815
|
+
var import_common6 = __toESM(require_src());
|
|
7816
|
+
async function disableJob(jobService, accessToken, jobName) {
|
|
7817
|
+
const requestId = import_common6.CorrelationService.createCorrelationContext();
|
|
7818
|
+
console.info(`Disabling job "${jobName}"...`);
|
|
7819
|
+
return jobService.disableJob(jobName, accessToken, requestId);
|
|
7820
|
+
}
|
|
7821
|
+
|
|
7822
|
+
// src/actions/jobs/enableJob.ts
|
|
7823
|
+
init_cjs_shims();
|
|
7824
|
+
var import_common7 = __toESM(require_src());
|
|
7825
|
+
async function enableJob(jobService, accessToken, jobName) {
|
|
7826
|
+
const requestId = import_common7.CorrelationService.createCorrelationContext();
|
|
7827
|
+
console.info(`Enabling job "${jobName}"...`);
|
|
7828
|
+
return jobService.enableJob(jobName, accessToken, requestId);
|
|
7829
|
+
}
|
|
7830
|
+
|
|
7831
|
+
// src/actions/jobs/downloadJob.ts
|
|
7832
|
+
init_cjs_shims();
|
|
7833
|
+
var import_fs = __toESM(require("fs"));
|
|
7235
7834
|
var import_path = __toESM(require("path"));
|
|
7236
|
-
var
|
|
7237
|
-
|
|
7238
|
-
|
|
7239
|
-
|
|
7240
|
-
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
const
|
|
7244
|
-
const
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7835
|
+
var import_common8 = __toESM(require_src());
|
|
7836
|
+
async function downloadJob(jobService, accessToken, jobName, outputPath) {
|
|
7837
|
+
const requestId = import_common8.CorrelationService.createCorrelationContext();
|
|
7838
|
+
console.info(`Fetching job "${jobName}"...`);
|
|
7839
|
+
const job = await jobService.getJob(jobName, accessToken, requestId);
|
|
7840
|
+
const inlineScript = job.jobDefinition.inlineScript;
|
|
7841
|
+
const decoded = (0, import_common8.decodeBase64Notebook)(inlineScript, `job "${jobName}"`);
|
|
7842
|
+
const sanitizedJobName = import_path.default.basename(jobName).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7843
|
+
const resolvedPath = import_path.default.resolve(outputPath ?? import_path.default.join(process.cwd(), `${sanitizedJobName}.ipynb`));
|
|
7844
|
+
await import_fs.default.promises.mkdir(import_path.default.dirname(resolvedPath), { recursive: true });
|
|
7845
|
+
await import_fs.default.promises.writeFile(resolvedPath, decoded, "utf-8");
|
|
7846
|
+
return resolvedPath;
|
|
7847
|
+
}
|
|
7848
|
+
|
|
7849
|
+
// src/actions/jobs/listJobRuns.ts
|
|
7850
|
+
init_cjs_shims();
|
|
7851
|
+
var import_common9 = __toESM(require_src());
|
|
7852
|
+
async function listJobRuns(jobService, accessToken, jobName) {
|
|
7853
|
+
const requestId = import_common9.CorrelationService.createCorrelationContext();
|
|
7854
|
+
console.info(`Fetching runs for job "${jobName}"...`);
|
|
7855
|
+
return jobService.listJobRuns(jobName, accessToken, requestId);
|
|
7856
|
+
}
|
|
7857
|
+
|
|
7858
|
+
// src/actions/jobs/getJobRun.ts
|
|
7859
|
+
init_cjs_shims();
|
|
7860
|
+
var import_common10 = __toESM(require_src());
|
|
7861
|
+
async function getJobRun(jobService, accessToken, jobName, runId) {
|
|
7862
|
+
const requestId = import_common10.CorrelationService.createCorrelationContext();
|
|
7863
|
+
console.info(`Fetching run "${runId}" for job "${jobName}"...`);
|
|
7864
|
+
return jobService.getJobRun(jobName, runId, accessToken, requestId);
|
|
7865
|
+
}
|
|
7866
|
+
|
|
7867
|
+
// src/actions/jobs/startJobRun.ts
|
|
7868
|
+
init_cjs_shims();
|
|
7869
|
+
var import_common11 = __toESM(require_src());
|
|
7870
|
+
async function startJobRun(jobService, accessToken, jobName) {
|
|
7871
|
+
const requestId = import_common11.CorrelationService.createCorrelationContext();
|
|
7872
|
+
console.info(`Starting run for job "${jobName}"...`);
|
|
7873
|
+
return jobService.startJobRun(jobName, accessToken, requestId);
|
|
7874
|
+
}
|
|
7875
|
+
|
|
7876
|
+
// src/actions/jobs/cancelJobRun.ts
|
|
7877
|
+
init_cjs_shims();
|
|
7878
|
+
var import_common12 = __toESM(require_src());
|
|
7879
|
+
async function cancelJobRun(jobService, accessToken, jobName, runId) {
|
|
7880
|
+
const requestId = import_common12.CorrelationService.createCorrelationContext();
|
|
7881
|
+
console.info(`Cancelling run "${runId}" for job "${jobName}"...`);
|
|
7882
|
+
return jobService.cancelJobRun(jobName, runId, accessToken, requestId);
|
|
7883
|
+
}
|
|
7884
|
+
|
|
7885
|
+
// src/actions/jobs/downloadJobRunNotebook.ts
|
|
7886
|
+
init_cjs_shims();
|
|
7887
|
+
var import_fs2 = __toESM(require("fs"));
|
|
7888
|
+
var import_path2 = __toESM(require("path"));
|
|
7889
|
+
var import_common13 = __toESM(require_src());
|
|
7890
|
+
async function downloadJobRunNotebook(jobService, accessToken, jobName, runId, outputPath) {
|
|
7891
|
+
const requestId = import_common13.CorrelationService.createCorrelationContext();
|
|
7892
|
+
console.info(`Fetching run "${runId}" for job "${jobName}"...`);
|
|
7893
|
+
const run = await jobService.getJobRun(jobName, runId, accessToken, requestId);
|
|
7894
|
+
const scriptSnapshot = run.scriptSnapshot;
|
|
7895
|
+
const decoded = (0, import_common13.decodeBase64Notebook)(scriptSnapshot, `run "${runId}" for job "${jobName}"`);
|
|
7896
|
+
const sanitizedJobName = import_path2.default.basename(jobName).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7897
|
+
const sanitizedRunId = import_path2.default.basename(runId).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7898
|
+
const defaultFileName = `${sanitizedJobName}_${sanitizedRunId}.ipynb`;
|
|
7899
|
+
const resolvedPath = import_path2.default.resolve(outputPath ?? import_path2.default.join(process.cwd(), defaultFileName));
|
|
7900
|
+
await import_fs2.default.promises.mkdir(import_path2.default.dirname(resolvedPath), { recursive: true });
|
|
7901
|
+
await import_fs2.default.promises.writeFile(resolvedPath, decoded, "utf-8");
|
|
7902
|
+
return resolvedPath;
|
|
7903
|
+
}
|
|
7904
|
+
|
|
7905
|
+
// src/actions/jobs/createJobDefinition.ts
|
|
7906
|
+
init_cjs_shims();
|
|
7907
|
+
var p2 = __toESM(require("@clack/prompts"));
|
|
7908
|
+
var path3 = __toESM(require("path"));
|
|
7909
|
+
|
|
7910
|
+
// src/utils/validator/jobDefinitionValidator.ts
|
|
7911
|
+
init_cjs_shims();
|
|
7912
|
+
var import_zod = require("zod");
|
|
7913
|
+
var ISO_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2})?)?$/;
|
|
7914
|
+
var JOB_TYPES = ["Notebook", "GraphNotebook", "Kql"];
|
|
7915
|
+
var NODE_SIZES = ["small", "medium", "large"];
|
|
7916
|
+
var REPEAT_FREQUENCIES = ["minutes", "hours", "days", "weeks", "months"];
|
|
7917
|
+
var INTERVAL_BOUNDS = {
|
|
7918
|
+
minutes: { min: 15, max: 720 },
|
|
7919
|
+
hours: { min: 1, max: 72 }
|
|
7920
|
+
};
|
|
7921
|
+
var FIXED_INTERVAL_FREQUENCIES = new Set(
|
|
7922
|
+
REPEAT_FREQUENCIES.filter((f) => !(f in INTERVAL_BOUNDS))
|
|
7923
|
+
);
|
|
7924
|
+
var JOB_NAME_PATTERN = /^[a-zA-Z0-9 _-]+$/;
|
|
7925
|
+
var JOB_NAME_PATTERN_MESSAGE = "Job name may only contain letters, numbers, spaces, hyphens, or underscores";
|
|
7926
|
+
var VALID_WEEK_DAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
|
|
7927
|
+
function isValidISODate(value) {
|
|
7928
|
+
if (!ISO_DATE_PATTERN.test(value)) {
|
|
7929
|
+
return false;
|
|
7256
7930
|
}
|
|
7931
|
+
return !isNaN(new Date(value).getTime());
|
|
7257
7932
|
}
|
|
7933
|
+
var timeTableSchema = import_zod.z.object({
|
|
7934
|
+
weekDays: import_zod.z.array(import_zod.z.enum(VALID_WEEK_DAYS)).optional(),
|
|
7935
|
+
monthDays: import_zod.z.array(import_zod.z.number().int().min(1).max(31)).optional()
|
|
7936
|
+
}).optional();
|
|
7937
|
+
var scheduleConfigSchema = import_zod.z.object({
|
|
7938
|
+
isEnabled: import_zod.z.boolean(),
|
|
7939
|
+
repeatFrequency: import_zod.z.enum(REPEAT_FREQUENCIES).optional(),
|
|
7940
|
+
interval: import_zod.z.number().int().positive().optional(),
|
|
7941
|
+
startTime: import_zod.z.string().optional(),
|
|
7942
|
+
endTime: import_zod.z.string().optional(),
|
|
7943
|
+
timeTable: timeTableSchema
|
|
7944
|
+
});
|
|
7945
|
+
var jobDefinitionValidator = import_zod.z.object({
|
|
7946
|
+
jobName: import_zod.z.string().min(1, "Job name is required").regex(JOB_NAME_PATTERN, JOB_NAME_PATTERN_MESSAGE),
|
|
7947
|
+
jobPath: import_zod.z.string().min(1, "Job path is required"),
|
|
7948
|
+
jobType: import_zod.z.enum(JOB_TYPES).optional(),
|
|
7949
|
+
jobDescription: import_zod.z.string().optional(),
|
|
7950
|
+
computeInfo: import_zod.z.object({
|
|
7951
|
+
nodeSize: import_zod.z.enum(NODE_SIZES)
|
|
7952
|
+
}).optional(),
|
|
7953
|
+
scheduleConfig: scheduleConfigSchema.optional(),
|
|
7954
|
+
inputTables: import_zod.z.array(import_zod.z.string()).optional(),
|
|
7955
|
+
outputTables: import_zod.z.array(import_zod.z.string()).optional(),
|
|
7956
|
+
runtimeArgs: import_zod.z.array(import_zod.z.string()).optional(),
|
|
7957
|
+
isDisabled: import_zod.z.boolean().optional()
|
|
7958
|
+
}).refine(
|
|
7959
|
+
(data) => {
|
|
7960
|
+
const jobType = data.jobType ?? "Notebook";
|
|
7961
|
+
if (jobType === "Kql") {
|
|
7962
|
+
return true;
|
|
7963
|
+
}
|
|
7964
|
+
return data.jobPath.toLowerCase().endsWith(".ipynb");
|
|
7965
|
+
},
|
|
7966
|
+
{ message: "Job path must be a Python notebook (.ipynb) file", path: ["jobPath"] }
|
|
7967
|
+
).refine(
|
|
7968
|
+
(data) => {
|
|
7969
|
+
if (data.scheduleConfig?.isEnabled) {
|
|
7970
|
+
return !!data.scheduleConfig.repeatFrequency;
|
|
7971
|
+
}
|
|
7972
|
+
return true;
|
|
7973
|
+
},
|
|
7974
|
+
{ message: "repeatFrequency is required for scheduled jobs", path: ["scheduleConfig", "repeatFrequency"] }
|
|
7975
|
+
).refine(
|
|
7976
|
+
(data) => {
|
|
7977
|
+
const sc = data.scheduleConfig;
|
|
7978
|
+
if (!sc?.isEnabled || !sc.repeatFrequency) {
|
|
7979
|
+
return true;
|
|
7980
|
+
}
|
|
7981
|
+
return sc.interval !== void 0;
|
|
7982
|
+
},
|
|
7983
|
+
{ message: "Interval is required for scheduled jobs", path: ["scheduleConfig", "interval"] }
|
|
7984
|
+
).refine(
|
|
7985
|
+
(data) => {
|
|
7986
|
+
const sc = data.scheduleConfig;
|
|
7987
|
+
if (!sc?.isEnabled || sc.interval === void 0 || !sc.repeatFrequency) {
|
|
7988
|
+
return true;
|
|
7989
|
+
}
|
|
7990
|
+
const bounds = INTERVAL_BOUNDS[sc.repeatFrequency];
|
|
7991
|
+
if (bounds) {
|
|
7992
|
+
return sc.interval >= bounds.min && sc.interval <= bounds.max;
|
|
7993
|
+
}
|
|
7994
|
+
if (FIXED_INTERVAL_FREQUENCIES.has(sc.repeatFrequency)) {
|
|
7995
|
+
return sc.interval === 1;
|
|
7996
|
+
}
|
|
7997
|
+
return true;
|
|
7998
|
+
},
|
|
7999
|
+
{
|
|
8000
|
+
message: "Schedule interval is out of range for the selected frequency",
|
|
8001
|
+
path: ["scheduleConfig", "interval"]
|
|
8002
|
+
}
|
|
8003
|
+
).refine(
|
|
8004
|
+
(data) => {
|
|
8005
|
+
const sc = data.scheduleConfig;
|
|
8006
|
+
if (!sc?.isEnabled || !sc.startTime) {
|
|
8007
|
+
return true;
|
|
8008
|
+
}
|
|
8009
|
+
return isValidISODate(sc.startTime);
|
|
8010
|
+
},
|
|
8011
|
+
{ message: "Start time must be a valid ISO 8601 date", path: ["scheduleConfig", "startTime"] }
|
|
8012
|
+
).refine(
|
|
8013
|
+
(data) => {
|
|
8014
|
+
const sc = data.scheduleConfig;
|
|
8015
|
+
if (!sc?.isEnabled || !sc.endTime) {
|
|
8016
|
+
return true;
|
|
8017
|
+
}
|
|
8018
|
+
return isValidISODate(sc.endTime);
|
|
8019
|
+
},
|
|
8020
|
+
{ message: "End time must be a valid ISO 8601 date", path: ["scheduleConfig", "endTime"] }
|
|
8021
|
+
).refine(
|
|
8022
|
+
(data) => {
|
|
8023
|
+
const sc = data.scheduleConfig;
|
|
8024
|
+
if (!sc?.isEnabled || !sc.startTime || !sc.endTime) {
|
|
8025
|
+
return true;
|
|
8026
|
+
}
|
|
8027
|
+
const start = new Date(sc.startTime);
|
|
8028
|
+
const end = new Date(sc.endTime);
|
|
8029
|
+
if (isNaN(start.getTime()) || isNaN(end.getTime())) {
|
|
8030
|
+
return true;
|
|
8031
|
+
}
|
|
8032
|
+
return end > start;
|
|
8033
|
+
},
|
|
8034
|
+
{ message: "End time must be after start time", path: ["scheduleConfig", "endTime"] }
|
|
8035
|
+
).refine(
|
|
8036
|
+
(data) => {
|
|
8037
|
+
const sc = data.scheduleConfig;
|
|
8038
|
+
if (!sc?.isEnabled || sc.repeatFrequency !== "weeks") {
|
|
8039
|
+
return true;
|
|
8040
|
+
}
|
|
8041
|
+
const days = sc.timeTable?.weekDays;
|
|
8042
|
+
return Array.isArray(days) && days.length > 0;
|
|
8043
|
+
},
|
|
8044
|
+
{ message: "At least one day of the week is required for weekly schedule", path: ["scheduleConfig", "timeTable"] }
|
|
8045
|
+
).refine(
|
|
8046
|
+
(data) => {
|
|
8047
|
+
const sc = data.scheduleConfig;
|
|
8048
|
+
if (!sc?.isEnabled || sc.repeatFrequency !== "months") {
|
|
8049
|
+
return true;
|
|
8050
|
+
}
|
|
8051
|
+
const days = sc.timeTable?.monthDays;
|
|
8052
|
+
return Array.isArray(days) && days.length > 0;
|
|
8053
|
+
},
|
|
8054
|
+
{
|
|
8055
|
+
message: "At least one day of the month is required for monthly schedule",
|
|
8056
|
+
path: ["scheduleConfig", "timeTable", "monthDays"]
|
|
8057
|
+
}
|
|
8058
|
+
);
|
|
7258
8059
|
|
|
7259
|
-
// src/
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
8060
|
+
// src/actions/jobs/promptHelpers.ts
|
|
8061
|
+
init_cjs_shims();
|
|
8062
|
+
var fs3 = __toESM(require("fs"));
|
|
8063
|
+
var p = __toESM(require("@clack/prompts"));
|
|
8064
|
+
var DEFAULT_NODE_SIZE = "large";
|
|
8065
|
+
var NODE_SIZE_OPTIONS = NODE_SIZES.map((size) => ({
|
|
8066
|
+
value: size,
|
|
8067
|
+
label: size === DEFAULT_NODE_SIZE ? `${capitalize(size)} (default)` : capitalize(size)
|
|
8068
|
+
}));
|
|
8069
|
+
var FREQUENCY_OPTIONS = REPEAT_FREQUENCIES.map((freq) => ({
|
|
8070
|
+
value: freq,
|
|
8071
|
+
label: capitalize(freq)
|
|
8072
|
+
}));
|
|
8073
|
+
var CONFIGURABLE_INTERVAL_FREQUENCIES = new Set(
|
|
8074
|
+
Object.keys(INTERVAL_BOUNDS)
|
|
8075
|
+
);
|
|
8076
|
+
var WEEKDAY_OPTIONS = [
|
|
8077
|
+
{ value: "Monday", label: "Monday" },
|
|
8078
|
+
{ value: "Tuesday", label: "Tuesday" },
|
|
8079
|
+
{ value: "Wednesday", label: "Wednesday" },
|
|
8080
|
+
{ value: "Thursday", label: "Thursday" },
|
|
8081
|
+
{ value: "Friday", label: "Friday" },
|
|
8082
|
+
{ value: "Saturday", label: "Saturday" },
|
|
8083
|
+
{ value: "Sunday", label: "Sunday" }
|
|
8084
|
+
];
|
|
8085
|
+
function capitalize(s) {
|
|
8086
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
8087
|
+
}
|
|
8088
|
+
function handleCancel(value) {
|
|
8089
|
+
if (p.isCancel(value)) {
|
|
8090
|
+
p.cancel("Operation cancelled.");
|
|
8091
|
+
process.exit(0);
|
|
7267
8092
|
}
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
8093
|
+
}
|
|
8094
|
+
async function promptIfMissing(flagValue, promptFn) {
|
|
8095
|
+
if (flagValue !== void 0) {
|
|
8096
|
+
return flagValue;
|
|
8097
|
+
}
|
|
8098
|
+
const result = await promptFn();
|
|
8099
|
+
handleCancel(result);
|
|
8100
|
+
return result;
|
|
8101
|
+
}
|
|
8102
|
+
function validateInterval(frequency) {
|
|
8103
|
+
return (v) => {
|
|
8104
|
+
if (!v || v.trim() === "") {
|
|
8105
|
+
return "Interval is required";
|
|
8106
|
+
}
|
|
8107
|
+
const trimmed = v.trim();
|
|
8108
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
8109
|
+
return "Please enter a whole number";
|
|
8110
|
+
}
|
|
8111
|
+
const n = parseInt(trimmed, 10);
|
|
8112
|
+
const bounds = INTERVAL_BOUNDS[frequency];
|
|
8113
|
+
if (bounds) {
|
|
8114
|
+
if (n < bounds.min) {
|
|
8115
|
+
return `Minimum value is ${bounds.min} ${frequency}`;
|
|
8116
|
+
}
|
|
8117
|
+
if (n > bounds.max) {
|
|
8118
|
+
return `Maximum value is ${bounds.max} ${frequency}`;
|
|
8119
|
+
}
|
|
8120
|
+
} else if (FIXED_INTERVAL_FREQUENCIES.has(frequency)) {
|
|
8121
|
+
if (n !== 1) {
|
|
8122
|
+
return `Interval must be 1 for ${frequency}`;
|
|
7283
8123
|
}
|
|
7284
8124
|
}
|
|
8125
|
+
return void 0;
|
|
7285
8126
|
};
|
|
7286
|
-
|
|
7287
|
-
|
|
7288
|
-
|
|
7289
|
-
|
|
8127
|
+
}
|
|
8128
|
+
function validateJobPath(v) {
|
|
8129
|
+
if (!v) {
|
|
8130
|
+
return "Job path is required";
|
|
7290
8131
|
}
|
|
7291
|
-
|
|
8132
|
+
if (!v.toLowerCase().endsWith(".ipynb")) {
|
|
8133
|
+
return "Job path must be a Python notebook (.ipynb) file";
|
|
8134
|
+
}
|
|
8135
|
+
if (!fs3.existsSync(v)) {
|
|
8136
|
+
return `File not found at "${v}". Please provide a valid path to an existing .ipynb file`;
|
|
8137
|
+
}
|
|
8138
|
+
return void 0;
|
|
7292
8139
|
}
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
var getMsalInstance = async (env, authorityOverride) => {
|
|
7297
|
-
const key = authorityOverride ?? env.aadEndpoint;
|
|
7298
|
-
if (!msalInstances.has(key)) {
|
|
7299
|
-
const config = await getMsalConfig(env, !process.env.CI, authorityOverride);
|
|
7300
|
-
msalInstances.set(key, new import_msal_node2.PublicClientApplication(config));
|
|
8140
|
+
function validateISODate(v) {
|
|
8141
|
+
if (!v) {
|
|
8142
|
+
return "Date/time is required";
|
|
7301
8143
|
}
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
if (error) {
|
|
7312
|
-
reject(new Error(`Failed to open browser: ${error.message}`));
|
|
7313
|
-
} else {
|
|
7314
|
-
resolve();
|
|
7315
|
-
}
|
|
7316
|
-
});
|
|
7317
|
-
});
|
|
8144
|
+
const iso8601Pattern = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2})?)?$/;
|
|
8145
|
+
if (!iso8601Pattern.test(v)) {
|
|
8146
|
+
return "Must be a valid ISO 8601 date (e.g. 2026-01-01T09:00:00Z)";
|
|
8147
|
+
}
|
|
8148
|
+
const d = new Date(v);
|
|
8149
|
+
if (isNaN(d.getTime())) {
|
|
8150
|
+
return "Must be a valid ISO 8601 date (e.g. 2026-01-01T09:00:00Z)";
|
|
8151
|
+
}
|
|
8152
|
+
return void 0;
|
|
7318
8153
|
}
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
const result = await msalInstance.acquireTokenInteractive({
|
|
7323
|
-
scopes,
|
|
7324
|
-
openBrowser: openSystemBrowser,
|
|
7325
|
-
successTemplate: "<h1>Authentication successful</h1><p>You may close this tab and return to the terminal.</p>",
|
|
7326
|
-
errorTemplate: "<h1>Authentication failed</h1><p>{error}</p>"
|
|
7327
|
-
});
|
|
7328
|
-
if (!result?.accessToken) {
|
|
7329
|
-
throw new Error("Token acquisition failed: received null or empty token.");
|
|
8154
|
+
function validateEndTimeAfterStart(startTime, endTime) {
|
|
8155
|
+
if (!endTime) {
|
|
8156
|
+
return "End time is required";
|
|
7330
8157
|
}
|
|
7331
|
-
|
|
7332
|
-
|
|
8158
|
+
const start = new Date(startTime);
|
|
8159
|
+
const end = new Date(endTime);
|
|
8160
|
+
if (isNaN(start.getTime()) || isNaN(end.getTime())) {
|
|
8161
|
+
return "Please enter valid date and time values";
|
|
8162
|
+
}
|
|
8163
|
+
if (end <= start) {
|
|
8164
|
+
return "End time must be after start time";
|
|
8165
|
+
}
|
|
8166
|
+
return void 0;
|
|
8167
|
+
}
|
|
8168
|
+
function validateJobName(v) {
|
|
8169
|
+
if (!v) {
|
|
8170
|
+
return "Job name is required";
|
|
8171
|
+
}
|
|
8172
|
+
if (!JOB_NAME_PATTERN.test(v)) {
|
|
8173
|
+
return JOB_NAME_PATTERN_MESSAGE;
|
|
8174
|
+
}
|
|
8175
|
+
return void 0;
|
|
8176
|
+
}
|
|
8177
|
+
function validateEndTime(startTime) {
|
|
8178
|
+
return (v) => {
|
|
8179
|
+
const isoErr = validateISODate(v);
|
|
8180
|
+
if (isoErr) {
|
|
8181
|
+
return isoErr;
|
|
8182
|
+
}
|
|
8183
|
+
return validateEndTimeAfterStart(startTime, v);
|
|
8184
|
+
};
|
|
7333
8185
|
}
|
|
7334
8186
|
|
|
7335
|
-
// src/
|
|
8187
|
+
// src/utils/yaml/yamlIO.ts
|
|
7336
8188
|
init_cjs_shims();
|
|
7337
|
-
var
|
|
7338
|
-
var
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
function saveBrokerAccount(account, authority) {
|
|
7345
|
-
import_fs.default.mkdirSync(SENTINEL_DIR, { recursive: true, mode: 448 });
|
|
7346
|
-
const session = { account, authority };
|
|
7347
|
-
const tempFile = `${BROKER_ACCOUNT_FILE}.tmp`;
|
|
7348
|
-
import_fs.default.writeFileSync(tempFile, JSON.stringify(session, null, 2), { encoding: "utf8", mode: 384 });
|
|
7349
|
-
import_fs.default.renameSync(tempFile, BROKER_ACCOUNT_FILE);
|
|
7350
|
-
}
|
|
7351
|
-
function loadBrokerAccount() {
|
|
8189
|
+
var fs4 = __toESM(require("fs"));
|
|
8190
|
+
var YAML = __toESM(require("yaml"));
|
|
8191
|
+
function readJobDefinitionYaml(filePath) {
|
|
8192
|
+
if (!fs4.existsSync(filePath)) {
|
|
8193
|
+
throw new Error(`File not found: ${filePath}`);
|
|
8194
|
+
}
|
|
8195
|
+
let raw;
|
|
7352
8196
|
try {
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
}
|
|
7359
|
-
}
|
|
7360
|
-
} catch {
|
|
8197
|
+
const content = fs4.readFileSync(filePath, "utf-8");
|
|
8198
|
+
raw = YAML.parse(content);
|
|
8199
|
+
} catch (err) {
|
|
8200
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
8201
|
+
throw new Error(`Failed to read/parse YAML: ${message}`);
|
|
7361
8202
|
}
|
|
7362
|
-
|
|
8203
|
+
const result = jobDefinitionValidator.safeParse(raw);
|
|
8204
|
+
if (result.success) {
|
|
8205
|
+
return result.data;
|
|
8206
|
+
}
|
|
8207
|
+
const issues = result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`);
|
|
8208
|
+
throw new Error(`Validation failed:
|
|
8209
|
+
${issues.join("\n")}`);
|
|
7363
8210
|
}
|
|
7364
|
-
function
|
|
8211
|
+
function writeJobDefinitionYaml(filePath, config) {
|
|
8212
|
+
const result = jobDefinitionValidator.safeParse(config);
|
|
8213
|
+
if (!result.success) {
|
|
8214
|
+
const issues = result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`);
|
|
8215
|
+
return { success: false, issues };
|
|
8216
|
+
}
|
|
7365
8217
|
try {
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
}
|
|
7369
|
-
} catch {
|
|
8218
|
+
const yamlContent = YAML.stringify(result.data, { lineWidth: 0 });
|
|
8219
|
+
fs4.writeFileSync(filePath, yamlContent, "utf-8");
|
|
8220
|
+
return { success: true, issues: [] };
|
|
8221
|
+
} catch (err) {
|
|
8222
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
8223
|
+
return { success: false, issues: [`Failed to write file "${filePath}": ${message}`] };
|
|
7370
8224
|
}
|
|
7371
8225
|
}
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
|
|
7381
|
-
|
|
7382
|
-
|
|
7383
|
-
|
|
7384
|
-
|
|
7385
|
-
|
|
7386
|
-
|
|
7387
|
-
|
|
8226
|
+
|
|
8227
|
+
// src/actions/jobs/createJobDefinition.ts
|
|
8228
|
+
function sanitizeFileName(fileName) {
|
|
8229
|
+
return fileName.replace(/[<>:"/\\|?*]/g, "_").replace(/\s+/g, "_");
|
|
8230
|
+
}
|
|
8231
|
+
function fail(message) {
|
|
8232
|
+
throw new Error(message);
|
|
8233
|
+
}
|
|
8234
|
+
async function collectJobDetails(jobNameArg, options) {
|
|
8235
|
+
const jobName = await promptIfMissing(
|
|
8236
|
+
jobNameArg,
|
|
8237
|
+
() => p2.text({
|
|
8238
|
+
message: "Job name:",
|
|
8239
|
+
validate: validateJobName
|
|
8240
|
+
})
|
|
8241
|
+
);
|
|
8242
|
+
if (jobNameArg !== void 0) {
|
|
8243
|
+
const nameError = validateJobName(jobName);
|
|
8244
|
+
if (nameError) {
|
|
8245
|
+
fail(nameError);
|
|
8246
|
+
}
|
|
8247
|
+
}
|
|
8248
|
+
const jobDescription = await promptIfMissing(
|
|
8249
|
+
options.description,
|
|
8250
|
+
() => p2.text({ message: "Description (optional):", defaultValue: "" })
|
|
8251
|
+
);
|
|
8252
|
+
const jobPath = await promptIfMissing(
|
|
8253
|
+
options.notebook,
|
|
8254
|
+
() => p2.text({
|
|
8255
|
+
message: "Job path (.ipynb):",
|
|
8256
|
+
placeholder: "path/to/notebook.ipynb",
|
|
8257
|
+
validate: validateJobPath
|
|
8258
|
+
})
|
|
8259
|
+
);
|
|
8260
|
+
if (options.notebook !== void 0) {
|
|
8261
|
+
const pathError = validateJobPath(jobPath);
|
|
8262
|
+
if (pathError) {
|
|
8263
|
+
fail(pathError);
|
|
8264
|
+
}
|
|
8265
|
+
}
|
|
8266
|
+
return { jobName, jobDescription, jobPath };
|
|
8267
|
+
}
|
|
8268
|
+
async function collectCompute(options) {
|
|
8269
|
+
if (options.cluster) {
|
|
8270
|
+
const normalized = options.cluster.toLowerCase();
|
|
8271
|
+
if (!NODE_SIZES.includes(normalized)) {
|
|
8272
|
+
fail(`Invalid cluster size "${options.cluster}". Must be one of: ${NODE_SIZES.join(", ")}`);
|
|
8273
|
+
}
|
|
8274
|
+
return normalized;
|
|
8275
|
+
}
|
|
8276
|
+
const result = await p2.select({
|
|
8277
|
+
message: "Cluster size:",
|
|
8278
|
+
options: NODE_SIZE_OPTIONS,
|
|
8279
|
+
initialValue: DEFAULT_NODE_SIZE
|
|
8280
|
+
});
|
|
8281
|
+
handleCancel(result);
|
|
8282
|
+
return result;
|
|
8283
|
+
}
|
|
8284
|
+
async function collectSchedule(options) {
|
|
8285
|
+
let wantsSchedule = !!options.schedule;
|
|
8286
|
+
if (!wantsSchedule) {
|
|
8287
|
+
const result = await p2.confirm({ message: "Schedule this job?", initialValue: true });
|
|
8288
|
+
handleCancel(result);
|
|
8289
|
+
wantsSchedule = result;
|
|
8290
|
+
}
|
|
8291
|
+
if (!wantsSchedule) {
|
|
8292
|
+
return { isEnabled: false };
|
|
8293
|
+
}
|
|
8294
|
+
const repeatFrequency = await promptIfMissing(
|
|
8295
|
+
options.schedule,
|
|
8296
|
+
() => p2.select({ message: "Repeat frequency:", options: FREQUENCY_OPTIONS })
|
|
8297
|
+
);
|
|
8298
|
+
if (options.schedule && !REPEAT_FREQUENCIES.includes(repeatFrequency)) {
|
|
8299
|
+
fail(`Invalid schedule frequency "${options.schedule}". Must be one of: ${REPEAT_FREQUENCIES.join(", ")}`);
|
|
8300
|
+
}
|
|
8301
|
+
let interval = 1;
|
|
8302
|
+
if (CONFIGURABLE_INTERVAL_FREQUENCIES.has(repeatFrequency)) {
|
|
8303
|
+
const intervalStr = await promptIfMissing(
|
|
8304
|
+
options.interval,
|
|
8305
|
+
() => p2.text({
|
|
8306
|
+
message: `Interval (${repeatFrequency}):`,
|
|
8307
|
+
defaultValue: repeatFrequency === "minutes" ? "15" : "1",
|
|
8308
|
+
validate: validateInterval(repeatFrequency)
|
|
8309
|
+
})
|
|
8310
|
+
);
|
|
8311
|
+
if (options.interval) {
|
|
8312
|
+
const intervalError = validateInterval(repeatFrequency)(intervalStr);
|
|
8313
|
+
if (intervalError) {
|
|
8314
|
+
fail(intervalError);
|
|
7388
8315
|
}
|
|
7389
|
-
} catch {
|
|
7390
|
-
console.warn("\u26A0\uFE0F Silent broker authentication with saved session failed. Trying getAllAccounts()...");
|
|
7391
8316
|
}
|
|
8317
|
+
interval = Number(intervalStr);
|
|
7392
8318
|
}
|
|
7393
|
-
|
|
7394
|
-
|
|
7395
|
-
|
|
7396
|
-
|
|
7397
|
-
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
|
|
8319
|
+
let timeTable;
|
|
8320
|
+
if (repeatFrequency === "weeks") {
|
|
8321
|
+
const result = await p2.multiselect({
|
|
8322
|
+
message: "Which days of the week?",
|
|
8323
|
+
options: [...WEEKDAY_OPTIONS],
|
|
8324
|
+
required: true
|
|
8325
|
+
});
|
|
8326
|
+
handleCancel(result);
|
|
8327
|
+
timeTable = { weekDays: result };
|
|
8328
|
+
}
|
|
8329
|
+
const startTime = await promptIfMissing(
|
|
8330
|
+
options.startTime,
|
|
8331
|
+
() => p2.text({
|
|
8332
|
+
message: "Start time (ISO 8601):",
|
|
8333
|
+
defaultValue: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8334
|
+
validate: validateISODate
|
|
8335
|
+
})
|
|
8336
|
+
);
|
|
8337
|
+
if (options.startTime) {
|
|
8338
|
+
const startError = validateISODate(startTime);
|
|
8339
|
+
if (startError) {
|
|
8340
|
+
fail(startError);
|
|
8341
|
+
}
|
|
8342
|
+
}
|
|
8343
|
+
if (repeatFrequency === "months") {
|
|
8344
|
+
const dayOfMonth = new Date(startTime).getDate();
|
|
8345
|
+
timeTable = { monthDays: [dayOfMonth] };
|
|
8346
|
+
}
|
|
8347
|
+
let endTime;
|
|
8348
|
+
if (options.endTime) {
|
|
8349
|
+
endTime = options.endTime;
|
|
8350
|
+
} else {
|
|
8351
|
+
let endTimeResolved = false;
|
|
8352
|
+
while (!endTimeResolved) {
|
|
8353
|
+
const setEndTime = await p2.confirm({ message: "Set an end time?", initialValue: false });
|
|
8354
|
+
handleCancel(setEndTime);
|
|
8355
|
+
if (setEndTime) {
|
|
8356
|
+
const result = await p2.text({
|
|
8357
|
+
message: "End time (ISO 8601):",
|
|
8358
|
+
validate: validateEndTime(startTime)
|
|
8359
|
+
});
|
|
8360
|
+
handleCancel(result);
|
|
8361
|
+
endTime = result;
|
|
8362
|
+
endTimeResolved = true;
|
|
8363
|
+
} else {
|
|
8364
|
+
p2.log.warn("This job will run indefinitely until manually stopped or deleted.");
|
|
8365
|
+
const confirmIndefinite = await p2.confirm({ message: "Run indefinitely?", initialValue: true });
|
|
8366
|
+
handleCancel(confirmIndefinite);
|
|
8367
|
+
if (confirmIndefinite) {
|
|
8368
|
+
endTimeResolved = true;
|
|
8369
|
+
}
|
|
7403
8370
|
}
|
|
7404
|
-
} catch {
|
|
7405
|
-
console.warn("\u26A0\uFE0F Silent broker authentication failed. Prompting interactively...");
|
|
7406
8371
|
}
|
|
7407
8372
|
}
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
openBrowser: async (_url) => {
|
|
8373
|
+
if (options.endTime) {
|
|
8374
|
+
const endError = validateEndTimeAfterStart(startTime, endTime);
|
|
8375
|
+
if (endError) {
|
|
8376
|
+
fail(endError);
|
|
7413
8377
|
}
|
|
7414
|
-
});
|
|
7415
|
-
if (!result?.accessToken) {
|
|
7416
|
-
throw new Error("Failed to acquire token via Windows Native Broker.");
|
|
7417
8378
|
}
|
|
7418
|
-
|
|
7419
|
-
|
|
8379
|
+
return { isEnabled: true, repeatFrequency, interval, startTime, endTime, timeTable };
|
|
8380
|
+
}
|
|
8381
|
+
async function createJobDefinition(jobNameArg, options) {
|
|
8382
|
+
p2.intro("Create a job definition");
|
|
8383
|
+
const { jobName, jobDescription, jobPath } = await collectJobDetails(jobNameArg, options);
|
|
8384
|
+
const nodeSize = await collectCompute(options);
|
|
8385
|
+
const schedule = await collectSchedule(options);
|
|
8386
|
+
const config = {
|
|
8387
|
+
jobName,
|
|
8388
|
+
jobPath,
|
|
8389
|
+
jobType: "Notebook",
|
|
8390
|
+
...jobDescription && { jobDescription },
|
|
8391
|
+
computeInfo: { nodeSize },
|
|
8392
|
+
...schedule.isEnabled && {
|
|
8393
|
+
scheduleConfig: {
|
|
8394
|
+
isEnabled: true,
|
|
8395
|
+
repeatFrequency: schedule.repeatFrequency,
|
|
8396
|
+
interval: schedule.interval,
|
|
8397
|
+
startTime: schedule.startTime,
|
|
8398
|
+
endTime: schedule.endTime,
|
|
8399
|
+
...schedule.timeTable && { timeTable: schedule.timeTable }
|
|
8400
|
+
}
|
|
8401
|
+
}
|
|
8402
|
+
};
|
|
8403
|
+
const outputPath = path3.resolve(options.output ?? `${sanitizeFileName(jobName)}.yaml`);
|
|
8404
|
+
const result = writeJobDefinitionYaml(outputPath, config);
|
|
8405
|
+
if (!result.success) {
|
|
8406
|
+
for (const issue of result.issues) {
|
|
8407
|
+
p2.log.error(issue);
|
|
8408
|
+
}
|
|
8409
|
+
throw new Error("Validation failed");
|
|
7420
8410
|
}
|
|
7421
|
-
|
|
7422
|
-
|
|
8411
|
+
p2.log.success(`Written to ${outputPath}`);
|
|
8412
|
+
p2.outro("Job definition created successfully!");
|
|
7423
8413
|
}
|
|
7424
8414
|
|
|
7425
|
-
// src/actions/
|
|
7426
|
-
init_cjs_shims();
|
|
7427
|
-
|
|
7428
|
-
// src/services/msalAuth.ts
|
|
8415
|
+
// src/actions/jobs/showJobDefinition.ts
|
|
7429
8416
|
init_cjs_shims();
|
|
7430
|
-
var import_common5 = __toESM(require_src());
|
|
7431
8417
|
|
|
7432
|
-
// src/
|
|
8418
|
+
// src/utils/formatter/outputFormatter.ts
|
|
7433
8419
|
init_cjs_shims();
|
|
7434
|
-
var
|
|
7435
|
-
var
|
|
7436
|
-
|
|
7437
|
-
|
|
8420
|
+
var COLUMN_SEPARATOR = " ";
|
|
8421
|
+
var HEADER_RULE_CHAR = "\u2500";
|
|
8422
|
+
var OutputFormatter = class {
|
|
8423
|
+
format;
|
|
8424
|
+
constructor(options = {}) {
|
|
8425
|
+
this.format = options.output ?? "table";
|
|
7438
8426
|
}
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
8427
|
+
/**
|
|
8428
|
+
* Renders `rows` to stdout using the configured output format.
|
|
8429
|
+
*
|
|
8430
|
+
* @param rows - The data array to render.
|
|
8431
|
+
* @param columns - Column descriptors that define headers and value extractors.
|
|
8432
|
+
*/
|
|
8433
|
+
print(rows, columns) {
|
|
8434
|
+
if (this.format === "json") {
|
|
8435
|
+
this.printJson(rows, columns);
|
|
8436
|
+
} else {
|
|
8437
|
+
this.printTable(rows, columns);
|
|
7442
8438
|
}
|
|
7443
|
-
return _DefaultCredentialProvider.instance;
|
|
7444
8439
|
}
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
8440
|
+
// ---------------------------------------------------------------------------
|
|
8441
|
+
// Table rendering
|
|
8442
|
+
// ---------------------------------------------------------------------------
|
|
8443
|
+
printTable(rows, columns) {
|
|
8444
|
+
if (rows.length === 0) {
|
|
8445
|
+
console.log("(no results)");
|
|
8446
|
+
return;
|
|
7450
8447
|
}
|
|
7451
|
-
|
|
8448
|
+
const widths = columns.map((col) => {
|
|
8449
|
+
const cellWidths = rows.map((row) => String(col.key(row) ?? "").length);
|
|
8450
|
+
return Math.max(col.header.length, ...cellWidths);
|
|
8451
|
+
});
|
|
8452
|
+
const header = columns.map((col, i) => col.header.padEnd(widths[i])).join(COLUMN_SEPARATOR);
|
|
8453
|
+
console.log(header);
|
|
8454
|
+
const rule = widths.map((w) => HEADER_RULE_CHAR.repeat(w)).join(COLUMN_SEPARATOR);
|
|
8455
|
+
console.log(rule);
|
|
8456
|
+
for (const row of rows) {
|
|
8457
|
+
const line = columns.map((col, i) => String(col.key(row) ?? "").padEnd(widths[i])).join(COLUMN_SEPARATOR);
|
|
8458
|
+
console.log(line);
|
|
8459
|
+
}
|
|
8460
|
+
}
|
|
8461
|
+
// ---------------------------------------------------------------------------
|
|
8462
|
+
// JSON rendering
|
|
8463
|
+
// ---------------------------------------------------------------------------
|
|
8464
|
+
printJson(rows, columns) {
|
|
8465
|
+
const records = rows.map((row) => {
|
|
8466
|
+
const record = {};
|
|
8467
|
+
for (const col of columns) {
|
|
8468
|
+
const key = col.jsonKey ?? col.header.toLowerCase();
|
|
8469
|
+
const value = col.key(row);
|
|
8470
|
+
record[key] = value ?? null;
|
|
8471
|
+
}
|
|
8472
|
+
return record;
|
|
8473
|
+
});
|
|
8474
|
+
console.log(JSON.stringify(records, null, 2));
|
|
7452
8475
|
}
|
|
7453
8476
|
};
|
|
7454
8477
|
|
|
7455
|
-
// src/
|
|
7456
|
-
var
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
}
|
|
8478
|
+
// src/actions/jobs/showJobDefinition.ts
|
|
8479
|
+
var FIELD_COLUMNS = [
|
|
8480
|
+
{ header: "FIELD", key: (f) => f.label },
|
|
8481
|
+
{ header: "VALUE", key: (f) => f.value }
|
|
8482
|
+
];
|
|
8483
|
+
function buildJobFields(data) {
|
|
8484
|
+
const fields = [
|
|
8485
|
+
{ label: "Name", value: data.jobName },
|
|
8486
|
+
{ label: "Description", value: data.jobDescription ?? "" },
|
|
8487
|
+
{ label: "Type", value: data.jobType ?? "" },
|
|
8488
|
+
{ label: "Job Path", value: data.jobPath },
|
|
8489
|
+
{ label: "Cluster", value: data.computeInfo?.nodeSize ? capitalize(data.computeInfo.nodeSize) : "" },
|
|
8490
|
+
{ label: "Disabled", value: data.isDisabled ? "Yes" : "No" }
|
|
8491
|
+
];
|
|
8492
|
+
const schedule = data.scheduleConfig;
|
|
8493
|
+
if (schedule?.isEnabled) {
|
|
8494
|
+
const freq = schedule.repeatFrequency ? capitalize(schedule.repeatFrequency) : "";
|
|
8495
|
+
const interval = schedule.interval ?? 1;
|
|
8496
|
+
fields.push({ label: "Schedule", value: `Every ${interval} ${freq}` });
|
|
8497
|
+
if (schedule.timeTable?.weekDays?.length) {
|
|
8498
|
+
fields.push({ label: "Weekly Days", value: schedule.timeTable.weekDays.join(", ") });
|
|
8499
|
+
}
|
|
8500
|
+
if (schedule.timeTable?.monthDays?.length) {
|
|
8501
|
+
fields.push({ label: "Monthly Days", value: schedule.timeTable.monthDays.join(", ") });
|
|
8502
|
+
}
|
|
8503
|
+
fields.push({ label: "Start Time", value: schedule.startTime ?? "" });
|
|
8504
|
+
fields.push({ label: "End Time", value: schedule.endTime ?? "(indefinite)" });
|
|
8505
|
+
} else {
|
|
8506
|
+
fields.push({ label: "Schedule", value: "On-demand" });
|
|
8507
|
+
}
|
|
8508
|
+
fields.push({ label: "Input Tables", value: data.inputTables?.length ? data.inputTables.join(", ") : "(none)" });
|
|
8509
|
+
fields.push({ label: "Output Tables", value: data.outputTables?.length ? data.outputTables.join(", ") : "(none)" });
|
|
8510
|
+
if (data.runtimeArgs?.length) {
|
|
8511
|
+
fields.push({ label: "Runtime Args", value: data.runtimeArgs.join(", ") });
|
|
8512
|
+
}
|
|
8513
|
+
return fields;
|
|
8514
|
+
}
|
|
8515
|
+
function showJobDefinition(filePath, options) {
|
|
8516
|
+
const data = readJobDefinitionYaml(filePath);
|
|
8517
|
+
const fmt = new OutputFormatter({ output: options.output ?? "table" });
|
|
8518
|
+
const fields = buildJobFields(data);
|
|
8519
|
+
fmt.print(fields, FIELD_COLUMNS);
|
|
8520
|
+
}
|
|
8521
|
+
|
|
8522
|
+
// src/actions/jobs/updateJobDefinition.ts
|
|
8523
|
+
init_cjs_shims();
|
|
8524
|
+
var p3 = __toESM(require("@clack/prompts"));
|
|
8525
|
+
var UPDATABLE_FIELDS = [
|
|
8526
|
+
{ value: "description", label: "Description" },
|
|
8527
|
+
{ value: "jobPath", label: "Job path" },
|
|
8528
|
+
{ value: "cluster", label: "Cluster size" },
|
|
8529
|
+
{ value: "schedule", label: "Schedule" },
|
|
8530
|
+
{ value: "inputTables", label: "Input tables" },
|
|
8531
|
+
{ value: "outputTables", label: "Output tables" },
|
|
8532
|
+
{ value: "runtimeArgs", label: "Runtime arguments" }
|
|
8533
|
+
];
|
|
8534
|
+
async function updateDescription(config) {
|
|
8535
|
+
const result = await p3.text({
|
|
8536
|
+
message: "New description:",
|
|
8537
|
+
defaultValue: config.jobDescription ?? ""
|
|
8538
|
+
});
|
|
8539
|
+
handleCancel(result);
|
|
8540
|
+
config.jobDescription = result;
|
|
8541
|
+
}
|
|
8542
|
+
async function updateJobPath(config) {
|
|
8543
|
+
const result = await p3.text({
|
|
8544
|
+
message: "New job path (.ipynb):",
|
|
8545
|
+
defaultValue: config.jobPath,
|
|
8546
|
+
validate: validateJobPath
|
|
8547
|
+
});
|
|
8548
|
+
handleCancel(result);
|
|
8549
|
+
config.jobPath = result;
|
|
8550
|
+
}
|
|
8551
|
+
async function updateCluster(config) {
|
|
8552
|
+
const result = await p3.select({
|
|
8553
|
+
message: "New cluster size:",
|
|
8554
|
+
options: NODE_SIZE_OPTIONS,
|
|
8555
|
+
initialValue: config.computeInfo?.nodeSize ?? DEFAULT_NODE_SIZE
|
|
8556
|
+
});
|
|
8557
|
+
handleCancel(result);
|
|
8558
|
+
config.computeInfo = { nodeSize: result };
|
|
8559
|
+
}
|
|
8560
|
+
async function updateSchedule(config) {
|
|
8561
|
+
const existing = config.scheduleConfig;
|
|
8562
|
+
const wantsSchedule = await p3.confirm({
|
|
8563
|
+
message: "Enable schedule?",
|
|
8564
|
+
initialValue: existing?.isEnabled ?? true
|
|
8565
|
+
});
|
|
8566
|
+
handleCancel(wantsSchedule);
|
|
8567
|
+
if (!wantsSchedule) {
|
|
8568
|
+
config.scheduleConfig = { isEnabled: false };
|
|
8569
|
+
return;
|
|
8570
|
+
}
|
|
8571
|
+
const frequency = await p3.select({
|
|
8572
|
+
message: "Repeat frequency:",
|
|
8573
|
+
options: FREQUENCY_OPTIONS,
|
|
8574
|
+
initialValue: existing?.repeatFrequency ?? "days"
|
|
8575
|
+
});
|
|
8576
|
+
handleCancel(frequency);
|
|
8577
|
+
const repeatFrequency = frequency;
|
|
8578
|
+
let interval = 1;
|
|
8579
|
+
if (CONFIGURABLE_INTERVAL_FREQUENCIES.has(repeatFrequency)) {
|
|
8580
|
+
const defaultInterval = existing?.interval ?? (repeatFrequency === "minutes" ? 15 : 1);
|
|
8581
|
+
const intervalStr = await p3.text({
|
|
8582
|
+
message: `Interval (${repeatFrequency}):`,
|
|
8583
|
+
defaultValue: String(defaultInterval),
|
|
8584
|
+
validate: validateInterval(repeatFrequency)
|
|
8585
|
+
});
|
|
8586
|
+
handleCancel(intervalStr);
|
|
8587
|
+
interval = Number(intervalStr);
|
|
8588
|
+
}
|
|
8589
|
+
let timeTable;
|
|
8590
|
+
if (repeatFrequency === "weeks") {
|
|
8591
|
+
const existingDays = existing?.timeTable?.weekDays ?? [];
|
|
8592
|
+
const result = await p3.multiselect({
|
|
8593
|
+
message: "Which days of the week?",
|
|
8594
|
+
options: WEEKDAY_OPTIONS.map((opt) => ({
|
|
8595
|
+
...opt,
|
|
8596
|
+
selected: existingDays.includes(opt.value)
|
|
8597
|
+
})),
|
|
8598
|
+
required: true
|
|
8599
|
+
});
|
|
8600
|
+
handleCancel(result);
|
|
8601
|
+
timeTable = { weekDays: result };
|
|
8602
|
+
}
|
|
8603
|
+
const startTime = await p3.text({
|
|
8604
|
+
message: "Start time (ISO 8601):",
|
|
8605
|
+
defaultValue: existing?.startTime ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
8606
|
+
validate: validateISODate
|
|
8607
|
+
});
|
|
8608
|
+
handleCancel(startTime);
|
|
8609
|
+
if (repeatFrequency === "months") {
|
|
8610
|
+
const dayOfMonth = new Date(startTime).getDate();
|
|
8611
|
+
timeTable = { monthDays: [dayOfMonth] };
|
|
8612
|
+
}
|
|
8613
|
+
let endTime;
|
|
8614
|
+
const setEndTime = await p3.confirm({
|
|
8615
|
+
message: "Set an end time?",
|
|
8616
|
+
initialValue: !!existing?.endTime
|
|
8617
|
+
});
|
|
8618
|
+
handleCancel(setEndTime);
|
|
8619
|
+
if (setEndTime) {
|
|
8620
|
+
const result = await p3.text({
|
|
8621
|
+
message: "End time (ISO 8601):",
|
|
8622
|
+
defaultValue: existing?.endTime ?? "",
|
|
8623
|
+
validate: validateEndTime(startTime)
|
|
8624
|
+
});
|
|
8625
|
+
handleCancel(result);
|
|
8626
|
+
endTime = result;
|
|
8627
|
+
}
|
|
8628
|
+
config.scheduleConfig = {
|
|
8629
|
+
isEnabled: true,
|
|
8630
|
+
repeatFrequency,
|
|
8631
|
+
interval,
|
|
8632
|
+
startTime,
|
|
8633
|
+
endTime,
|
|
8634
|
+
...timeTable && { timeTable }
|
|
7464
8635
|
};
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
8636
|
+
}
|
|
8637
|
+
async function updateStringArray(config, field, label) {
|
|
8638
|
+
const current = config[field] ?? [];
|
|
8639
|
+
const result = await p3.text({
|
|
8640
|
+
message: `${label} (comma-separated):`,
|
|
8641
|
+
defaultValue: current.join(", ")
|
|
8642
|
+
});
|
|
8643
|
+
handleCancel(result);
|
|
8644
|
+
const raw = result;
|
|
8645
|
+
config[field] = raw.trim() ? raw.split(",").map((s) => s.trim()) : [];
|
|
8646
|
+
}
|
|
8647
|
+
async function applyFieldUpdate(field, config) {
|
|
8648
|
+
switch (field) {
|
|
8649
|
+
case "description":
|
|
8650
|
+
return updateDescription(config);
|
|
8651
|
+
case "jobPath":
|
|
8652
|
+
return updateJobPath(config);
|
|
8653
|
+
case "cluster":
|
|
8654
|
+
return updateCluster(config);
|
|
8655
|
+
case "schedule":
|
|
8656
|
+
return updateSchedule(config);
|
|
8657
|
+
case "inputTables":
|
|
8658
|
+
return updateStringArray(config, "inputTables", "Input tables");
|
|
8659
|
+
case "outputTables":
|
|
8660
|
+
return updateStringArray(config, "outputTables", "Output tables");
|
|
8661
|
+
case "runtimeArgs":
|
|
8662
|
+
return updateStringArray(config, "runtimeArgs", "Runtime arguments");
|
|
7469
8663
|
}
|
|
7470
|
-
console.log("\u2705 Authenticated using Device Code Flow");
|
|
7471
|
-
return result.accessToken;
|
|
7472
8664
|
}
|
|
7473
|
-
async function
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
|
|
7481
|
-
|
|
7482
|
-
|
|
8665
|
+
async function updateJobDefinition(filePath) {
|
|
8666
|
+
p3.intro("Update job definition");
|
|
8667
|
+
const data = readJobDefinitionYaml(filePath);
|
|
8668
|
+
let editing = true;
|
|
8669
|
+
while (editing) {
|
|
8670
|
+
const field = await p3.select({
|
|
8671
|
+
message: "Which field to update?",
|
|
8672
|
+
options: [...UPDATABLE_FIELDS]
|
|
8673
|
+
});
|
|
8674
|
+
handleCancel(field);
|
|
8675
|
+
await applyFieldUpdate(field, data);
|
|
8676
|
+
const again = await p3.confirm({ message: "Update another field?", initialValue: false });
|
|
8677
|
+
handleCancel(again);
|
|
8678
|
+
editing = again;
|
|
8679
|
+
}
|
|
8680
|
+
const result = writeJobDefinitionYaml(filePath, data);
|
|
8681
|
+
if (!result.success) {
|
|
8682
|
+
for (const issue of result.issues) {
|
|
8683
|
+
p3.log.error(issue);
|
|
7483
8684
|
}
|
|
7484
|
-
|
|
7485
|
-
console.error("\u274C Logout failed:", error instanceof Error ? error.message : "Unknown error");
|
|
7486
|
-
} finally {
|
|
7487
|
-
deleteBrokerAccount();
|
|
8685
|
+
throw new Error("Validation failed");
|
|
7488
8686
|
}
|
|
8687
|
+
p3.log.success(`Updated ${filePath}`);
|
|
8688
|
+
p3.outro("Done");
|
|
7489
8689
|
}
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
|
|
8690
|
+
|
|
8691
|
+
// src/utils/error/handleApiError.ts
|
|
8692
|
+
init_cjs_shims();
|
|
8693
|
+
function hasStatusCode(e) {
|
|
8694
|
+
return e instanceof Error && "statusCode" in e && typeof e.statusCode === "number";
|
|
8695
|
+
}
|
|
8696
|
+
function hasResponseStatus(e) {
|
|
8697
|
+
return e instanceof Error && "response" in e && e.response !== null && typeof e.response?.status === "number";
|
|
8698
|
+
}
|
|
8699
|
+
function getStatusInfo(error) {
|
|
8700
|
+
if (hasStatusCode(error)) {
|
|
8701
|
+
return ` (HTTP ${error.statusCode})`;
|
|
7495
8702
|
}
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
|
|
8703
|
+
if (hasResponseStatus(error)) {
|
|
8704
|
+
return ` (HTTP ${error.response.status})`;
|
|
8705
|
+
}
|
|
8706
|
+
return "";
|
|
8707
|
+
}
|
|
8708
|
+
function handleApiError(context, error) {
|
|
8709
|
+
if (error instanceof Error) {
|
|
8710
|
+
console.error(`Error ${context}${getStatusInfo(error)}:`, error.message);
|
|
8711
|
+
if (process.env.DEBUG && error.stack) {
|
|
8712
|
+
console.error(error.stack);
|
|
8713
|
+
}
|
|
8714
|
+
process.exitCode = 1;
|
|
8715
|
+
throw error;
|
|
8716
|
+
}
|
|
8717
|
+
const wrapped = new Error(`Unknown error ${context}: ${String(error)}`, { cause: error });
|
|
8718
|
+
console.error(wrapped.message);
|
|
8719
|
+
process.exitCode = 1;
|
|
8720
|
+
throw wrapped;
|
|
8721
|
+
}
|
|
8722
|
+
|
|
8723
|
+
// src/commands/jobs/jobDefinitionCreate.ts
|
|
8724
|
+
function addJobDefinitionCreateCommand(definitionCommand) {
|
|
8725
|
+
definitionCommand.command("create [jobName]").description("Interactively create a job definition YAML file").option("--notebook <path>", "Path to the job file (.ipynb)").option("--description <text>", "Job description").option("--cluster <size>", "Cluster size (small | medium | large)").option("--schedule <frequency>", "Schedule frequency (minutes | hours | days | weeks | months)").option("--interval <number>", "Schedule interval").option("--start-time <datetime>", "Schedule start time (ISO 8601)").option("--end-time <datetime>", "Schedule end time (ISO 8601)").option("--output <path>", "Output YAML file path (default: ./<jobName>.yaml)").action(async (jobName, options) => {
|
|
7500
8726
|
try {
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
8727
|
+
await createJobDefinition(jobName, options);
|
|
8728
|
+
} catch (error) {
|
|
8729
|
+
handleApiError("creating job definition", error);
|
|
8730
|
+
}
|
|
8731
|
+
});
|
|
8732
|
+
}
|
|
8733
|
+
|
|
8734
|
+
// src/commands/jobs/jobDefinitionShow.ts
|
|
8735
|
+
init_cjs_shims();
|
|
8736
|
+
function addJobDefinitionShowCommand(definitionCommand) {
|
|
8737
|
+
definitionCommand.command("show <path>").description("Display a job definition YAML file").option("--output <format>", "Output format (table | json)", "table").action((filePath, options) => {
|
|
8738
|
+
try {
|
|
8739
|
+
showJobDefinition(filePath, options);
|
|
8740
|
+
} catch (error) {
|
|
8741
|
+
handleApiError("showing job definition", error);
|
|
8742
|
+
}
|
|
8743
|
+
});
|
|
8744
|
+
}
|
|
8745
|
+
|
|
8746
|
+
// src/commands/jobs/jobDefinitionUpdate.ts
|
|
8747
|
+
init_cjs_shims();
|
|
8748
|
+
function addJobDefinitionUpdateCommand(definitionCommand) {
|
|
8749
|
+
definitionCommand.command("update <path>").description("Interactively update a job definition YAML file").action(async (filePath) => {
|
|
8750
|
+
try {
|
|
8751
|
+
await updateJobDefinition(filePath);
|
|
8752
|
+
} catch (error) {
|
|
8753
|
+
handleApiError("updating job definition", error);
|
|
7512
8754
|
}
|
|
8755
|
+
});
|
|
8756
|
+
}
|
|
8757
|
+
|
|
8758
|
+
// src/commands/jobs/jobDelete.ts
|
|
8759
|
+
init_cjs_shims();
|
|
8760
|
+
var import_common21 = __toESM(require_src());
|
|
8761
|
+
|
|
8762
|
+
// src/services/jobs/index.ts
|
|
8763
|
+
init_cjs_shims();
|
|
8764
|
+
|
|
8765
|
+
// src/services/jobs/jobService.ts
|
|
8766
|
+
init_cjs_shims();
|
|
8767
|
+
var JobService = class {
|
|
8768
|
+
constructor(jobApiClient) {
|
|
8769
|
+
this.jobApiClient = jobApiClient;
|
|
8770
|
+
}
|
|
8771
|
+
async listJobs(accessToken, requestId) {
|
|
8772
|
+
return this.jobApiClient.listJobs(accessToken, requestId);
|
|
8773
|
+
}
|
|
8774
|
+
async getJob(jobName, accessToken, requestId) {
|
|
8775
|
+
return this.jobApiClient.getJob(jobName, accessToken, requestId);
|
|
8776
|
+
}
|
|
8777
|
+
async deleteJob(jobName, accessToken, requestId) {
|
|
8778
|
+
return this.jobApiClient.deleteJob(jobName, accessToken, requestId);
|
|
8779
|
+
}
|
|
8780
|
+
async disableJob(jobName, accessToken, requestId) {
|
|
8781
|
+
return this.jobApiClient.disableJob(jobName, accessToken, requestId);
|
|
8782
|
+
}
|
|
8783
|
+
async enableJob(jobName, accessToken, requestId) {
|
|
8784
|
+
return this.jobApiClient.enableJob(jobName, accessToken, requestId);
|
|
8785
|
+
}
|
|
8786
|
+
async listJobRuns(jobName, accessToken, requestId) {
|
|
8787
|
+
return this.jobApiClient.listJobRuns(jobName, accessToken, requestId);
|
|
8788
|
+
}
|
|
8789
|
+
async getJobRun(jobName, runId, accessToken, requestId) {
|
|
8790
|
+
return this.jobApiClient.getJobRun(jobName, runId, accessToken, requestId);
|
|
8791
|
+
}
|
|
8792
|
+
async startJobRun(jobName, accessToken, requestId) {
|
|
8793
|
+
return this.jobApiClient.startJobRun(jobName, accessToken, requestId);
|
|
8794
|
+
}
|
|
8795
|
+
async cancelJobRun(jobName, runId, accessToken, requestId) {
|
|
8796
|
+
return this.jobApiClient.cancelJobRun(jobName, runId, accessToken, requestId);
|
|
8797
|
+
}
|
|
8798
|
+
};
|
|
8799
|
+
|
|
8800
|
+
// src/services/getToken.ts
|
|
8801
|
+
init_cjs_shims();
|
|
8802
|
+
var import_common17 = __toESM(require_src());
|
|
8803
|
+
|
|
8804
|
+
// src/auth/constants.ts
|
|
8805
|
+
init_cjs_shims();
|
|
8806
|
+
|
|
8807
|
+
// src/auth/provider/TokenProviderFactory.ts
|
|
8808
|
+
init_cjs_shims();
|
|
8809
|
+
|
|
8810
|
+
// src/auth/provider/DeviceCodeTokenProvider.ts
|
|
8811
|
+
init_cjs_shims();
|
|
8812
|
+
|
|
8813
|
+
// src/services/msalAuth.ts
|
|
8814
|
+
init_cjs_shims();
|
|
8815
|
+
|
|
8816
|
+
// src/auth/msalInstance.ts
|
|
8817
|
+
init_cjs_shims();
|
|
8818
|
+
var import_msal_node2 = require("@azure/msal-node");
|
|
8819
|
+
|
|
8820
|
+
// src/config/msalConfig.ts
|
|
8821
|
+
init_cjs_shims();
|
|
8822
|
+
var import_msal_node = require("@azure/msal-node");
|
|
8823
|
+
var import_msal_node_extensions2 = require("@azure/msal-node-extensions");
|
|
8824
|
+
|
|
8825
|
+
// src/auth/persistence/persistence.ts
|
|
8826
|
+
init_cjs_shims();
|
|
8827
|
+
var import_msal_node_extensions = require("@azure/msal-node-extensions");
|
|
8828
|
+
var import_os = __toESM(require("os"));
|
|
8829
|
+
var import_path3 = __toESM(require("path"));
|
|
8830
|
+
var PlatformType = /* @__PURE__ */ ((PlatformType2) => {
|
|
8831
|
+
PlatformType2["Windows"] = "win32";
|
|
8832
|
+
PlatformType2["MacOS"] = "darwin";
|
|
8833
|
+
PlatformType2["Linux"] = "linux";
|
|
8834
|
+
return PlatformType2;
|
|
8835
|
+
})(PlatformType || {});
|
|
8836
|
+
async function createPersistence() {
|
|
8837
|
+
const cacheFilePath = import_path3.default.join(import_os.default.homedir(), ".nsdcli-cache.json");
|
|
8838
|
+
const platform5 = import_os.default.platform();
|
|
8839
|
+
switch (platform5) {
|
|
8840
|
+
case "win32" /* Windows */:
|
|
8841
|
+
return await import_msal_node_extensions.FilePersistenceWithDataProtection.create(cacheFilePath, import_msal_node_extensions.DataProtectionScope.CurrentUser);
|
|
8842
|
+
case "darwin" /* MacOS */:
|
|
8843
|
+
return await import_msal_node_extensions.KeychainPersistence.create("nsdcli.service", "nsdcli.account", "nsdcli");
|
|
8844
|
+
case "linux" /* Linux */:
|
|
8845
|
+
return await import_msal_node_extensions.LibSecretPersistence.create("nsdcli.service", "nsdcli.account", "nsdcli");
|
|
8846
|
+
default:
|
|
8847
|
+
throw new Error(
|
|
8848
|
+
`Unsupported platform: ${platform5}. Supported platforms are: ${Object.values(PlatformType).join(", ")}`
|
|
8849
|
+
);
|
|
8850
|
+
}
|
|
8851
|
+
}
|
|
8852
|
+
|
|
8853
|
+
// src/config/msalConfig.ts
|
|
8854
|
+
var os2 = __toESM(require("os"));
|
|
8855
|
+
async function getMsalConfig(environment, useCachePlugin = true, authorityOverride) {
|
|
8856
|
+
let cachePlugin;
|
|
8857
|
+
if (useCachePlugin) {
|
|
8858
|
+
const persistence = await createPersistence();
|
|
8859
|
+
await persistence.verifyPersistence();
|
|
8860
|
+
cachePlugin = new import_msal_node_extensions2.PersistenceCachePlugin(persistence);
|
|
8861
|
+
}
|
|
8862
|
+
const config = {
|
|
8863
|
+
auth: {
|
|
8864
|
+
clientId: environment.aadClientId,
|
|
8865
|
+
authority: authorityOverride ?? environment.aadEndpoint
|
|
8866
|
+
},
|
|
8867
|
+
cache: cachePlugin ? { cachePlugin } : void 0,
|
|
8868
|
+
system: {
|
|
8869
|
+
loggerOptions: {
|
|
8870
|
+
// Suppress all MSAL internal logs from appearing in CLI output.
|
|
8871
|
+
// MSAL's Info/Verbose messages are library internals not useful to end users.
|
|
8872
|
+
// Only Warning and above are passed to this callback, and we intentionally
|
|
8873
|
+
// discard them to keep the CLI output clean.
|
|
8874
|
+
loggerCallback() {
|
|
8875
|
+
},
|
|
8876
|
+
logLevel: import_msal_node.LogLevel.Warning,
|
|
8877
|
+
piiLoggingEnabled: false
|
|
8878
|
+
}
|
|
8879
|
+
}
|
|
8880
|
+
};
|
|
8881
|
+
if ("win32" /* Windows */ === os2.platform()) {
|
|
8882
|
+
config.broker = {
|
|
8883
|
+
nativeBrokerPlugin: new import_msal_node_extensions2.NativeBrokerPlugin()
|
|
8884
|
+
};
|
|
8885
|
+
}
|
|
8886
|
+
return config;
|
|
8887
|
+
}
|
|
8888
|
+
|
|
8889
|
+
// src/auth/msalInstance.ts
|
|
8890
|
+
var msalInstances = /* @__PURE__ */ new Map();
|
|
8891
|
+
var getMsalInstance = async (env, authorityOverride) => {
|
|
8892
|
+
const key = authorityOverride ?? env.aadEndpoint;
|
|
8893
|
+
if (!msalInstances.has(key)) {
|
|
8894
|
+
const config = await getMsalConfig(env, !process.env.CI, authorityOverride);
|
|
8895
|
+
msalInstances.set(key, new import_msal_node2.PublicClientApplication(config));
|
|
8896
|
+
}
|
|
8897
|
+
return msalInstances.get(key);
|
|
8898
|
+
};
|
|
8899
|
+
|
|
8900
|
+
// src/services/msalAuth.ts
|
|
8901
|
+
var import_common15 = __toESM(require_src());
|
|
8902
|
+
|
|
8903
|
+
// src/actions/defaultLogin.ts
|
|
8904
|
+
init_cjs_shims();
|
|
8905
|
+
var import_identity = require("@azure/identity");
|
|
8906
|
+
var DefaultCredentialProvider = class _DefaultCredentialProvider {
|
|
8907
|
+
static instance;
|
|
8908
|
+
constructor() {
|
|
8909
|
+
}
|
|
8910
|
+
static getInstance() {
|
|
8911
|
+
if (!_DefaultCredentialProvider.instance) {
|
|
8912
|
+
_DefaultCredentialProvider.instance = new _DefaultCredentialProvider();
|
|
8913
|
+
}
|
|
8914
|
+
return _DefaultCredentialProvider.instance;
|
|
8915
|
+
}
|
|
8916
|
+
async getToken(scopes) {
|
|
8917
|
+
const credential = new import_identity.DefaultAzureCredential();
|
|
8918
|
+
const token = await credential.getToken(scopes);
|
|
8919
|
+
if (!token) {
|
|
8920
|
+
throw new Error("Failed to acquire token using DefaultAzureCredential.");
|
|
8921
|
+
}
|
|
8922
|
+
return token;
|
|
8923
|
+
}
|
|
8924
|
+
};
|
|
8925
|
+
|
|
8926
|
+
// src/actions/brokerLogin.ts
|
|
8927
|
+
init_cjs_shims();
|
|
8928
|
+
var import_common14 = __toESM(require_src());
|
|
8929
|
+
var import_fs3 = __toESM(require("fs"));
|
|
8930
|
+
var import_os2 = __toESM(require("os"));
|
|
8931
|
+
var import_path4 = __toESM(require("path"));
|
|
8932
|
+
var apiEnv = (0, import_common14.getApiEnv)(import_common14.SecurityPlatformEnvironment.Production);
|
|
8933
|
+
var SENTINEL_DIR = import_path4.default.join(import_os2.default.homedir(), ".sentinel");
|
|
8934
|
+
var BROKER_ACCOUNT_FILE = import_path4.default.join(SENTINEL_DIR, "broker-account.json");
|
|
8935
|
+
function saveBrokerAccount(account, authority) {
|
|
8936
|
+
import_fs3.default.mkdirSync(SENTINEL_DIR, { recursive: true, mode: 448 });
|
|
8937
|
+
const session = { account, authority };
|
|
8938
|
+
const tempFile = `${BROKER_ACCOUNT_FILE}.tmp`;
|
|
8939
|
+
import_fs3.default.writeFileSync(tempFile, JSON.stringify(session, null, 2), { encoding: "utf8", mode: 384 });
|
|
8940
|
+
import_fs3.default.renameSync(tempFile, BROKER_ACCOUNT_FILE);
|
|
8941
|
+
}
|
|
8942
|
+
function loadBrokerAccount() {
|
|
8943
|
+
try {
|
|
8944
|
+
if (import_fs3.default.existsSync(BROKER_ACCOUNT_FILE)) {
|
|
8945
|
+
const raw = import_fs3.default.readFileSync(BROKER_ACCOUNT_FILE, "utf8");
|
|
8946
|
+
const session = JSON.parse(raw);
|
|
8947
|
+
if (session.account && typeof session.account === "object" && session.authority && typeof session.authority === "string") {
|
|
8948
|
+
return session;
|
|
8949
|
+
}
|
|
8950
|
+
}
|
|
8951
|
+
} catch {
|
|
8952
|
+
}
|
|
8953
|
+
return null;
|
|
8954
|
+
}
|
|
8955
|
+
function deleteBrokerAccount() {
|
|
8956
|
+
try {
|
|
8957
|
+
if (import_fs3.default.existsSync(BROKER_ACCOUNT_FILE)) {
|
|
8958
|
+
import_fs3.default.unlinkSync(BROKER_ACCOUNT_FILE);
|
|
8959
|
+
}
|
|
8960
|
+
} catch {
|
|
8961
|
+
}
|
|
8962
|
+
}
|
|
8963
|
+
async function brokerLogin(scopes, tenant) {
|
|
8964
|
+
const authorityOverride = tenant ? `${new URL(apiEnv.aadEndpoint).origin}/${tenant}` : void 0;
|
|
8965
|
+
const authority = authorityOverride ?? apiEnv.aadEndpoint;
|
|
8966
|
+
const msalInstance = await getMsalInstance(apiEnv, authorityOverride);
|
|
8967
|
+
const savedSession = loadBrokerAccount();
|
|
8968
|
+
const accounts = await msalInstance.getTokenCache().getAllAccounts();
|
|
8969
|
+
if (savedSession) {
|
|
8970
|
+
try {
|
|
8971
|
+
const silentResult = await msalInstance.acquireTokenSilent({
|
|
8972
|
+
account: savedSession.account,
|
|
8973
|
+
scopes,
|
|
8974
|
+
authority: savedSession.authority
|
|
8975
|
+
});
|
|
8976
|
+
if (silentResult?.accessToken) {
|
|
8977
|
+
console.log("\u2705 Authenticated silently via saved broker session.");
|
|
8978
|
+
return silentResult.accessToken;
|
|
8979
|
+
}
|
|
8980
|
+
} catch {
|
|
8981
|
+
console.warn("\u26A0\uFE0F Silent broker authentication with saved session failed. Trying getAllAccounts()...");
|
|
8982
|
+
}
|
|
8983
|
+
}
|
|
8984
|
+
if (accounts.length > 0) {
|
|
8985
|
+
try {
|
|
8986
|
+
const silentResult = await msalInstance.acquireTokenSilent({
|
|
8987
|
+
account: accounts[0],
|
|
8988
|
+
scopes
|
|
8989
|
+
});
|
|
8990
|
+
if (silentResult?.accessToken) {
|
|
8991
|
+
saveBrokerAccount(accounts[0], authority);
|
|
8992
|
+
console.log("\u2705 Authenticated silently via Windows Native Broker (SSO).");
|
|
8993
|
+
return silentResult.accessToken;
|
|
8994
|
+
}
|
|
8995
|
+
} catch {
|
|
8996
|
+
console.warn("\u26A0\uFE0F Silent broker authentication failed. Prompting interactively...");
|
|
8997
|
+
}
|
|
8998
|
+
}
|
|
8999
|
+
const result = await msalInstance.acquireTokenInteractive({
|
|
9000
|
+
scopes,
|
|
9001
|
+
prompt: "select_account",
|
|
9002
|
+
windowHandle: Buffer.alloc(0),
|
|
9003
|
+
// headless / console window handle
|
|
9004
|
+
openBrowser: async (_url) => {
|
|
9005
|
+
}
|
|
9006
|
+
});
|
|
9007
|
+
if (!result?.accessToken) {
|
|
9008
|
+
throw new Error("Failed to acquire token via Windows Native Broker.");
|
|
9009
|
+
}
|
|
9010
|
+
if (result.account) {
|
|
9011
|
+
saveBrokerAccount(result.account, authority);
|
|
9012
|
+
}
|
|
9013
|
+
console.log("\u2705 Authenticated via Windows Native Broker.");
|
|
9014
|
+
return result.accessToken;
|
|
9015
|
+
}
|
|
9016
|
+
|
|
9017
|
+
// src/services/msalAuth.ts
|
|
9018
|
+
var apiEnv2 = (0, import_common15.getApiEnv)(import_common15.SecurityPlatformEnvironment.Production);
|
|
9019
|
+
async function loginAndGetDeviceCodeToken(scopes = [apiEnv2.gatewayAuthResourceUri]) {
|
|
9020
|
+
const deviceCodeRequest = {
|
|
9021
|
+
scopes,
|
|
9022
|
+
deviceCodeCallback: (response) => {
|
|
9023
|
+
console.log(response.message);
|
|
9024
|
+
}
|
|
9025
|
+
};
|
|
9026
|
+
const msalInstance = await getMsalInstance(apiEnv2);
|
|
9027
|
+
const result = await msalInstance.acquireTokenByDeviceCode(deviceCodeRequest);
|
|
9028
|
+
if (!result || !result.accessToken) {
|
|
9029
|
+
throw new Error("Failed to acquire access token.");
|
|
9030
|
+
}
|
|
9031
|
+
console.log("\u2705 Authenticated using Device Code Flow");
|
|
9032
|
+
return result.accessToken;
|
|
9033
|
+
}
|
|
9034
|
+
async function logout() {
|
|
9035
|
+
try {
|
|
9036
|
+
const msalInstance = await getMsalInstance(apiEnv2);
|
|
9037
|
+
const accounts = await msalInstance.getTokenCache().getAllAccounts();
|
|
9038
|
+
if (accounts.length === 0) {
|
|
9039
|
+
console.log("\u2139 No cached accounts.");
|
|
9040
|
+
return;
|
|
9041
|
+
} else {
|
|
9042
|
+
await msalInstance.getTokenCache().removeAccount(accounts[0]);
|
|
9043
|
+
console.log("\u{1F44B} Logged out successfully.");
|
|
9044
|
+
}
|
|
9045
|
+
} catch (error) {
|
|
9046
|
+
console.error("\u274C Logout failed:", error instanceof Error ? error.message : "Unknown error");
|
|
9047
|
+
} finally {
|
|
9048
|
+
deleteBrokerAccount();
|
|
9049
|
+
}
|
|
9050
|
+
}
|
|
9051
|
+
async function getAccessTokenFromCache(scopes = [apiEnv2.gatewayAuthResourceUri]) {
|
|
9052
|
+
if (process.env.CI) {
|
|
9053
|
+
const defaultCredentialProvider = DefaultCredentialProvider.getInstance();
|
|
9054
|
+
const token = await defaultCredentialProvider.getToken(scopes);
|
|
9055
|
+
return token.token;
|
|
9056
|
+
}
|
|
9057
|
+
console.log("\u{1F510} Checking MSAL cache for tokens...");
|
|
9058
|
+
const savedSession = loadBrokerAccount();
|
|
9059
|
+
if (savedSession) {
|
|
9060
|
+
const authoritySegment = (() => {
|
|
9061
|
+
try {
|
|
9062
|
+
return new URL(savedSession.authority).pathname.split("/").filter(Boolean).pop() ?? "";
|
|
9063
|
+
} catch {
|
|
9064
|
+
return "";
|
|
9065
|
+
}
|
|
9066
|
+
})();
|
|
9067
|
+
const expectedTid = authoritySegment && authoritySegment !== "common" && authoritySegment !== "organizations" && authoritySegment !== "consumers" ? authoritySegment : null;
|
|
9068
|
+
try {
|
|
9069
|
+
const sessionMsal = await getMsalInstance(apiEnv2, savedSession.authority);
|
|
9070
|
+
const response = await sessionMsal.acquireTokenSilent({
|
|
9071
|
+
account: savedSession.account,
|
|
9072
|
+
scopes,
|
|
9073
|
+
authority: savedSession.authority
|
|
9074
|
+
});
|
|
9075
|
+
if (response?.accessToken) {
|
|
9076
|
+
if (expectedTid && response.account?.tenantId && response.account.tenantId !== expectedTid) {
|
|
9077
|
+
throw new Error(
|
|
9078
|
+
`Active tenant is ${expectedTid} but silent acquisition returned a token for ${response.account.tenantId}. Run 'sentinel login --tenant ${expectedTid}' (or 'sentinel tenant select') to mint a tenant-bound token.`
|
|
9079
|
+
);
|
|
9080
|
+
}
|
|
9081
|
+
console.log("\u2705 Authenticated using MSAL cache");
|
|
9082
|
+
return response.accessToken;
|
|
9083
|
+
}
|
|
9084
|
+
throw new Error(
|
|
9085
|
+
`Silent token acquisition returned no access token for the active tenant${expectedTid ? ` (${expectedTid})` : ""}. Run 'sentinel login${expectedTid ? ` --tenant ${expectedTid}` : ""}' to refresh credentials.`
|
|
9086
|
+
);
|
|
9087
|
+
} catch (err) {
|
|
9088
|
+
throw err instanceof Error ? err : new Error(`Silent token acquisition failed: ${String(err)}`);
|
|
9089
|
+
}
|
|
9090
|
+
}
|
|
9091
|
+
const msalInstance = await getMsalInstance(apiEnv2);
|
|
9092
|
+
const accounts = await msalInstance.getTokenCache().getAllAccounts();
|
|
9093
|
+
if (accounts.length > 0) {
|
|
9094
|
+
try {
|
|
9095
|
+
const response = await msalInstance.acquireTokenSilent({
|
|
9096
|
+
account: accounts[0],
|
|
9097
|
+
scopes
|
|
9098
|
+
});
|
|
9099
|
+
if (response?.accessToken) {
|
|
9100
|
+
console.log("\u2705 Authenticated using MSAL cache");
|
|
9101
|
+
return response.accessToken;
|
|
9102
|
+
}
|
|
9103
|
+
console.warn("\u26A0\uFE0F Silent token acquisition returned no access token");
|
|
9104
|
+
} catch {
|
|
9105
|
+
console.warn("\u26A0\uFE0F Silent token acquisition failed");
|
|
9106
|
+
}
|
|
9107
|
+
}
|
|
9108
|
+
return "";
|
|
9109
|
+
}
|
|
9110
|
+
|
|
9111
|
+
// src/auth/provider/DeviceCodeTokenProvider.ts
|
|
9112
|
+
var DeviceCodeTokenProvider = class {
|
|
9113
|
+
options;
|
|
9114
|
+
env;
|
|
9115
|
+
constructor(env, options) {
|
|
9116
|
+
if (!env) {
|
|
9117
|
+
throw new Error("Environment cannot be null or undefined");
|
|
9118
|
+
}
|
|
9119
|
+
this.env = env;
|
|
9120
|
+
this.options = {
|
|
9121
|
+
...options,
|
|
9122
|
+
// overrides defaults if user provided values
|
|
9123
|
+
scopes: options?.scopes ?? [this.env.gatewayAuthResourceUri]
|
|
9124
|
+
};
|
|
9125
|
+
}
|
|
9126
|
+
async getAccessToken() {
|
|
9127
|
+
let token = await getAccessTokenFromCache(this.options?.scopes);
|
|
9128
|
+
if (token) {
|
|
9129
|
+
return token;
|
|
9130
|
+
}
|
|
9131
|
+
token = await loginAndGetDeviceCodeToken(this.options?.scopes);
|
|
9132
|
+
return token;
|
|
9133
|
+
}
|
|
9134
|
+
};
|
|
9135
|
+
|
|
9136
|
+
// src/auth/provider/ManagedIdentityTokenProvider.ts
|
|
9137
|
+
init_cjs_shims();
|
|
9138
|
+
var import_identity2 = require("@azure/identity");
|
|
9139
|
+
var ManagedIdentityTokenProvider = class {
|
|
9140
|
+
options;
|
|
9141
|
+
env;
|
|
9142
|
+
constructor(env, options) {
|
|
9143
|
+
if (!env) {
|
|
9144
|
+
throw new Error("Environment cannot be null or undefined");
|
|
9145
|
+
}
|
|
9146
|
+
if (!options?.uamiClientId) {
|
|
9147
|
+
throw new Error("UAMI clientId required for user-assigned managed identity");
|
|
9148
|
+
}
|
|
9149
|
+
this.env = env;
|
|
9150
|
+
this.options = {
|
|
9151
|
+
...options,
|
|
9152
|
+
// overrides defaults if user provided values
|
|
9153
|
+
scopes: options?.scopes ?? [env.gatewayAuthResourceUri]
|
|
9154
|
+
};
|
|
9155
|
+
}
|
|
9156
|
+
async getAccessToken() {
|
|
9157
|
+
const scopes = this.options?.scopes && this.options.scopes.length > 0 ? this.options.scopes : [this.env.gatewayAuthResourceUri];
|
|
9158
|
+
const credential = new import_identity2.ManagedIdentityCredential({
|
|
9159
|
+
clientId: this.options?.uamiClientId
|
|
9160
|
+
});
|
|
9161
|
+
const token = await credential.getToken(scopes);
|
|
9162
|
+
if (!token) {
|
|
9163
|
+
throw new Error("Failed to get token from Managed Identity");
|
|
9164
|
+
}
|
|
9165
|
+
return token.token;
|
|
9166
|
+
}
|
|
9167
|
+
};
|
|
9168
|
+
|
|
9169
|
+
// src/auth/provider/MsalCacheTokenProvider.ts
|
|
9170
|
+
init_cjs_shims();
|
|
9171
|
+
var MsalCacheTokenProvider = class {
|
|
9172
|
+
options;
|
|
9173
|
+
env;
|
|
9174
|
+
constructor(env, options) {
|
|
9175
|
+
if (!env) {
|
|
9176
|
+
throw new Error("Environment cannot be null or undefined");
|
|
9177
|
+
}
|
|
9178
|
+
this.env = env;
|
|
9179
|
+
this.options = {
|
|
9180
|
+
...options,
|
|
9181
|
+
scopes: options?.scopes?.length ? options.scopes : [this.env.gatewayAuthResourceUri]
|
|
9182
|
+
};
|
|
9183
|
+
}
|
|
9184
|
+
async getAccessToken() {
|
|
9185
|
+
const token = await getAccessTokenFromCache(this.options.scopes);
|
|
9186
|
+
if (!token) {
|
|
9187
|
+
throw new Error("No cached authentication token found. Please run `sentinel login` first.");
|
|
9188
|
+
}
|
|
9189
|
+
return token;
|
|
9190
|
+
}
|
|
9191
|
+
};
|
|
9192
|
+
|
|
9193
|
+
// src/auth/provider/TokenProviderFactory.ts
|
|
9194
|
+
var TokenProviderFactory = class {
|
|
9195
|
+
static createProvider(env, method, options) {
|
|
9196
|
+
switch (method) {
|
|
9197
|
+
case "device_code":
|
|
9198
|
+
return new DeviceCodeTokenProvider(env, options);
|
|
9199
|
+
case "managed_identity":
|
|
9200
|
+
if (!options) {
|
|
9201
|
+
throw new Error("UAMI clientId required for user-assigned managed identity");
|
|
9202
|
+
}
|
|
9203
|
+
return new ManagedIdentityTokenProvider(env, options);
|
|
9204
|
+
case "msal_cache":
|
|
9205
|
+
return new MsalCacheTokenProvider(env, options);
|
|
9206
|
+
default:
|
|
9207
|
+
throw new Error(`Unsupported token method: ${method}`);
|
|
9208
|
+
}
|
|
9209
|
+
}
|
|
9210
|
+
};
|
|
9211
|
+
|
|
9212
|
+
// src/telemetry/index.ts
|
|
9213
|
+
init_cjs_shims();
|
|
9214
|
+
|
|
9215
|
+
// src/telemetry/telemetryService.ts
|
|
9216
|
+
init_cjs_shims();
|
|
9217
|
+
var import_common16 = __toESM(require_src());
|
|
9218
|
+
var import_api = require("@opentelemetry/api");
|
|
9219
|
+
var import_monitor_opentelemetry = require("@azure/monitor-opentelemetry");
|
|
9220
|
+
|
|
9221
|
+
// src/telemetry/connectionString.ts
|
|
9222
|
+
init_cjs_shims();
|
|
9223
|
+
var APPLICATION_INSIGHTS_CONNECTION_STRING = "InstrumentationKey=0dadb494-ecd4-44a5-bcc1-baa55b3778be;IngestionEndpoint=https://eastus-8.in.applicationinsights.azure.com/;LiveEndpoint=https://eastus.livediagnostics.monitor.azure.com/;ApplicationId=8bc9c85a-22a3-45f8-b4f5-0bb6cd6ddad2";
|
|
9224
|
+
|
|
9225
|
+
// src/telemetry/types.ts
|
|
9226
|
+
init_cjs_shims();
|
|
9227
|
+
var TELEMETRY_OPT_OUT_ENV_VARS = ["SENTINEL_TELEMETRY_OPTOUT", "DO_NOT_TRACK"];
|
|
9228
|
+
|
|
9229
|
+
// src/telemetry/commonProperties.ts
|
|
9230
|
+
init_cjs_shims();
|
|
9231
|
+
var os4 = __toESM(require("os"));
|
|
9232
|
+
var import_uuid = require("uuid");
|
|
9233
|
+
function readAppVersion() {
|
|
9234
|
+
return true ? "0.3.0" : "unknown";
|
|
9235
|
+
}
|
|
9236
|
+
function detectCiEnvironment(env = process.env) {
|
|
9237
|
+
if (env.TF_BUILD) {
|
|
9238
|
+
return "AzureDevOps";
|
|
9239
|
+
}
|
|
9240
|
+
if (env.GITHUB_ACTIONS) {
|
|
9241
|
+
return "GitHubActions";
|
|
9242
|
+
}
|
|
9243
|
+
if (env.BUILD_BUILDID) {
|
|
9244
|
+
return "AzureDevOps";
|
|
9245
|
+
}
|
|
9246
|
+
if (env.JENKINS_URL) {
|
|
9247
|
+
return "Jenkins";
|
|
9248
|
+
}
|
|
9249
|
+
if (env.CIRCLECI) {
|
|
9250
|
+
return "CircleCI";
|
|
9251
|
+
}
|
|
9252
|
+
if (env.GITLAB_CI) {
|
|
9253
|
+
return "GitLab";
|
|
9254
|
+
}
|
|
9255
|
+
if (env.CI) {
|
|
9256
|
+
return "Generic";
|
|
9257
|
+
}
|
|
9258
|
+
return "unknown";
|
|
9259
|
+
}
|
|
9260
|
+
function buildCommonProperties(sessionId = (0, import_uuid.v4)()) {
|
|
9261
|
+
return {
|
|
9262
|
+
appName: "sentinel-cli",
|
|
9263
|
+
appVersion: readAppVersion(),
|
|
9264
|
+
nodeVersion: process.versions.node,
|
|
9265
|
+
platform: process.platform,
|
|
9266
|
+
arch: process.arch,
|
|
9267
|
+
osRelease: os4.release(),
|
|
9268
|
+
sessionId,
|
|
9269
|
+
ciEnvironment: detectCiEnvironment()
|
|
9270
|
+
};
|
|
9271
|
+
}
|
|
9272
|
+
|
|
9273
|
+
// src/telemetry/redact.ts
|
|
9274
|
+
init_cjs_shims();
|
|
9275
|
+
var EMAIL_RE = /[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}/gi;
|
|
9276
|
+
var GUID_RE = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi;
|
|
9277
|
+
var JWT_RE = /(?<![A-Za-z0-9_-])eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}(?![A-Za-z0-9_-])/g;
|
|
9278
|
+
var UNIX_PATH_RE = /(?<![A-Za-z0-9_./\\-])(?:\/[^\s]+\/([^\s/]+)|\/([^\s/]+))/g;
|
|
9279
|
+
var WIN_PATH_RE = /(?<![A-Za-z0-9_./\\-])(?:[a-zA-Z]:\\[^\s]+\\([^\s\\]+)|[a-zA-Z]:\\([^\s\\]+))/g;
|
|
9280
|
+
function redactString(input) {
|
|
9281
|
+
if (!input) {
|
|
9282
|
+
return input;
|
|
9283
|
+
}
|
|
9284
|
+
return input.replace(JWT_RE, "<jwt>").replace(EMAIL_RE, "<email>").replace(GUID_RE, "<guid>").replace(UNIX_PATH_RE, (_m, deepBase, rootBase) => `<redacted>/${deepBase ?? rootBase}`).replace(WIN_PATH_RE, (_m, deepBase, rootBase) => `<redacted>\\${deepBase ?? rootBase}`);
|
|
9285
|
+
}
|
|
9286
|
+
function redactError(error) {
|
|
9287
|
+
const name = error.name || "Error";
|
|
9288
|
+
const message = redactString(error.message ?? "");
|
|
9289
|
+
const stack = error.stack ? error.stack.split("\n").slice(0, 4).map((line) => redactString(line)).join("\n") : "";
|
|
9290
|
+
return {
|
|
9291
|
+
errorName: name,
|
|
9292
|
+
errorMessage: message,
|
|
9293
|
+
errorStack: stack
|
|
9294
|
+
};
|
|
9295
|
+
}
|
|
9296
|
+
|
|
9297
|
+
// src/telemetry/telemetryService.ts
|
|
9298
|
+
var TRACER_NAME = "sentinel-cli";
|
|
9299
|
+
var TRACER_VERSION = "1.0.0";
|
|
9300
|
+
var azureMonitorInitialized = false;
|
|
9301
|
+
var TelemetryService = class _TelemetryService {
|
|
9302
|
+
sharedProperties = {};
|
|
9303
|
+
commonProperties;
|
|
9304
|
+
enabled;
|
|
9305
|
+
initialized = false;
|
|
9306
|
+
disposed = false;
|
|
9307
|
+
tracer;
|
|
9308
|
+
constructor(options = {}) {
|
|
9309
|
+
this.enabled = _TelemetryService.resolveEnabled(options);
|
|
9310
|
+
this.commonProperties = buildCommonProperties(options.sessionId);
|
|
9311
|
+
if (this.enabled) {
|
|
9312
|
+
this.initialize(options.connectionString ?? APPLICATION_INSIGHTS_CONNECTION_STRING);
|
|
9313
|
+
}
|
|
9314
|
+
}
|
|
9315
|
+
/** Determine whether telemetry should be active for this process. */
|
|
9316
|
+
static resolveEnabled(options) {
|
|
9317
|
+
if (options.forceDisabled) {
|
|
9318
|
+
return false;
|
|
9319
|
+
}
|
|
9320
|
+
for (const name of TELEMETRY_OPT_OUT_ENV_VARS) {
|
|
9321
|
+
if (process.env[name] === "1" || process.env[name]?.toLowerCase() === "true") {
|
|
9322
|
+
return false;
|
|
9323
|
+
}
|
|
9324
|
+
}
|
|
9325
|
+
return true;
|
|
9326
|
+
}
|
|
9327
|
+
/**
|
|
9328
|
+
* Initialise the Azure Monitor OpenTelemetry distro exactly once per
|
|
9329
|
+
* process, then acquire this instance's tracer. `useAzureMonitor()`
|
|
9330
|
+
* installs global SDK state (TracerProvider, exporters, processors), so
|
|
9331
|
+
* it is guarded by a module-level flag; `trace.getTracer()` is cheap and
|
|
9332
|
+
* idempotent so it is safe to call for every instance.
|
|
9333
|
+
*
|
|
9334
|
+
* Resource configuration is applied via OpenTelemetry env vars, set
|
|
9335
|
+
* programmatically *before* `useAzureMonitor()` so they're observed by
|
|
9336
|
+
* the SDK's resource-detection bootstrap:
|
|
9337
|
+
*
|
|
9338
|
+
* - `OTEL_NODE_RESOURCE_DETECTORS` — restricted to `env,os,serviceinstance`
|
|
9339
|
+
* so the `HostDetector` is **never** registered. This suppresses
|
|
9340
|
+
* `host.name` (device hostname, PII like `User-MacBook-Pro.local`),
|
|
9341
|
+
* `host.id` (stable hardware fingerprint), and `host.arch`.
|
|
9342
|
+
* - `OTEL_SERVICE_NAME` — populates `service.name`, which Azure Monitor
|
|
9343
|
+
* maps to `cloud_RoleName`. Without this, the backend records the OTel
|
|
9344
|
+
* default `"unknown_service:node"`.
|
|
9345
|
+
* - `OTEL_RESOURCE_ATTRIBUTES` — adds `service.version` (no dedicated env
|
|
9346
|
+
* var exists for it).
|
|
9347
|
+
*
|
|
9348
|
+
* Each variable is set with `??=` so any caller-provided override (e.g.
|
|
9349
|
+
* tests, advanced users) wins.
|
|
9350
|
+
*/
|
|
9351
|
+
initialize(connectionString) {
|
|
9352
|
+
if (!azureMonitorInitialized) {
|
|
9353
|
+
process.env.OTEL_NODE_RESOURCE_DETECTORS ??= "env,os,serviceinstance";
|
|
9354
|
+
process.env.OTEL_SERVICE_NAME ??= TRACER_NAME;
|
|
9355
|
+
process.env.OTEL_RESOURCE_ATTRIBUTES ??= `service.version=${TRACER_VERSION}`;
|
|
9356
|
+
(0, import_monitor_opentelemetry.useAzureMonitor)({
|
|
9357
|
+
azureMonitorExporterOptions: { connectionString },
|
|
9358
|
+
tracesPerSecond: 0,
|
|
9359
|
+
samplingRatio: 1
|
|
9360
|
+
});
|
|
9361
|
+
azureMonitorInitialized = true;
|
|
9362
|
+
}
|
|
9363
|
+
this.tracer = import_api.trace.getTracer(TRACER_NAME, TRACER_VERSION);
|
|
9364
|
+
this.initialized = true;
|
|
9365
|
+
}
|
|
9366
|
+
/**
|
|
9367
|
+
* Merge common + shared + caller-supplied properties into a flat
|
|
9368
|
+
* {@link Attributes} bag suitable for an OTel span. Primitive values
|
|
9369
|
+
* (`number`, `boolean`) are passed through unchanged so that downstream
|
|
9370
|
+
* Azure Monitor / Log Analytics queries see their native types instead
|
|
9371
|
+
* of stringified versions (which would break numeric aggregations and
|
|
9372
|
+
* boolean comparisons).
|
|
9373
|
+
*/
|
|
9374
|
+
mergeAttributes(extra) {
|
|
9375
|
+
const result = {
|
|
9376
|
+
...this.commonProperties,
|
|
9377
|
+
...this.sharedProperties
|
|
9378
|
+
};
|
|
9379
|
+
if (extra) {
|
|
9380
|
+
for (const [key, value] of Object.entries(extra)) {
|
|
9381
|
+
if (value === void 0) {
|
|
9382
|
+
continue;
|
|
9383
|
+
}
|
|
9384
|
+
result[key] = value;
|
|
9385
|
+
}
|
|
9386
|
+
}
|
|
9387
|
+
return result;
|
|
9388
|
+
}
|
|
9389
|
+
event(eventName, data) {
|
|
9390
|
+
if (!this.enabled || this.disposed || !this.tracer) {
|
|
9391
|
+
return;
|
|
9392
|
+
}
|
|
9393
|
+
const span = this.tracer.startSpan(eventName, {
|
|
9394
|
+
attributes: this.mergeAttributes(data?.properties)
|
|
9395
|
+
});
|
|
9396
|
+
if (data?.measurements) {
|
|
9397
|
+
for (const [k, v] of Object.entries(data.measurements)) {
|
|
9398
|
+
span.setAttribute(k, v);
|
|
9399
|
+
}
|
|
9400
|
+
}
|
|
9401
|
+
span.end();
|
|
9402
|
+
}
|
|
9403
|
+
span(eventName, initialAttributes) {
|
|
9404
|
+
if (!this.enabled || this.disposed || !this.tracer) {
|
|
9405
|
+
return new NoopSpanContext(eventName, initialAttributes);
|
|
9406
|
+
}
|
|
9407
|
+
return new TelemetrySpanContext(
|
|
9408
|
+
this.tracer,
|
|
9409
|
+
eventName,
|
|
9410
|
+
initialAttributes,
|
|
9411
|
+
(extras) => this.mergeAttributes(extras)
|
|
9412
|
+
);
|
|
9413
|
+
}
|
|
9414
|
+
setSharedProperty(name, value) {
|
|
9415
|
+
if (value === void 0) {
|
|
9416
|
+
delete this.sharedProperties[name];
|
|
9417
|
+
} else {
|
|
9418
|
+
this.sharedProperties[name] = value;
|
|
9419
|
+
}
|
|
9420
|
+
}
|
|
9421
|
+
getSharedProperties() {
|
|
9422
|
+
return { ...this.sharedProperties };
|
|
9423
|
+
}
|
|
9424
|
+
async dispose() {
|
|
9425
|
+
if (this.disposed) {
|
|
9426
|
+
return;
|
|
9427
|
+
}
|
|
9428
|
+
this.disposed = true;
|
|
9429
|
+
if (!this.enabled || !this.initialized) {
|
|
9430
|
+
return;
|
|
9431
|
+
}
|
|
9432
|
+
try {
|
|
9433
|
+
await (0, import_monitor_opentelemetry.shutdownAzureMonitor)();
|
|
9434
|
+
} catch {
|
|
9435
|
+
} finally {
|
|
9436
|
+
this.tracer = void 0;
|
|
9437
|
+
azureMonitorInitialized = false;
|
|
9438
|
+
}
|
|
9439
|
+
}
|
|
9440
|
+
};
|
|
9441
|
+
var TelemetrySpanContext = class {
|
|
9442
|
+
startTime = Date.now();
|
|
9443
|
+
eventName;
|
|
9444
|
+
attributes;
|
|
9445
|
+
otSpan;
|
|
9446
|
+
requestId;
|
|
9447
|
+
mergeAttributes;
|
|
9448
|
+
ended = false;
|
|
9449
|
+
constructor(tracer, eventName, initialAttributes, mergeAttributes) {
|
|
9450
|
+
this.eventName = eventName;
|
|
9451
|
+
this.attributes = { ...initialAttributes ?? {} };
|
|
9452
|
+
this.requestId = this.attributes.requestId ?? import_common16.CorrelationService.createCorrelationContext();
|
|
9453
|
+
this.attributes.requestId = this.requestId;
|
|
9454
|
+
this.mergeAttributes = mergeAttributes;
|
|
9455
|
+
this.otSpan = tracer.startSpan(eventName, {
|
|
9456
|
+
attributes: this.mergeAttributes(this.attributes)
|
|
9457
|
+
});
|
|
9458
|
+
}
|
|
9459
|
+
getRequestId() {
|
|
9460
|
+
return this.requestId;
|
|
9461
|
+
}
|
|
9462
|
+
addAttributes(extra) {
|
|
9463
|
+
this.applyAttributes(extra);
|
|
9464
|
+
}
|
|
9465
|
+
end(extra) {
|
|
9466
|
+
if (this.ended) {
|
|
9467
|
+
return;
|
|
9468
|
+
}
|
|
9469
|
+
this.applyAttributes(extra);
|
|
9470
|
+
this.finalize();
|
|
9471
|
+
}
|
|
9472
|
+
error(err, extra) {
|
|
9473
|
+
if (this.ended) {
|
|
9474
|
+
return;
|
|
9475
|
+
}
|
|
9476
|
+
const redacted = redactError(err);
|
|
9477
|
+
this.applyAttributes({ ...extra, ...redacted, success: false });
|
|
9478
|
+
const sanitized = new Error(redacted.errorMessage);
|
|
9479
|
+
sanitized.name = redacted.errorName;
|
|
9480
|
+
sanitized.stack = redacted.errorStack;
|
|
9481
|
+
this.otSpan.recordException(sanitized);
|
|
9482
|
+
this.otSpan.setStatus({ code: import_api.SpanStatusCode.ERROR, message: redacted.errorMessage });
|
|
9483
|
+
this.finalize();
|
|
9484
|
+
}
|
|
9485
|
+
/**
|
|
9486
|
+
* Merge non-undefined entries into both the local bag and the OTel span.
|
|
9487
|
+
* Values keep their native primitive type (`string | number | boolean`)
|
|
9488
|
+
* so the backing SDK records typed attributes rather than stringified ones.
|
|
9489
|
+
*/
|
|
9490
|
+
applyAttributes(extra) {
|
|
9491
|
+
if (!extra) {
|
|
9492
|
+
return;
|
|
9493
|
+
}
|
|
9494
|
+
for (const [k, v] of Object.entries(extra)) {
|
|
9495
|
+
if (v === void 0) {
|
|
9496
|
+
continue;
|
|
9497
|
+
}
|
|
9498
|
+
this.attributes[k] = v;
|
|
9499
|
+
this.otSpan.setAttribute(k, v);
|
|
9500
|
+
}
|
|
9501
|
+
}
|
|
9502
|
+
/** Stamp duration, close the OTel span, and flip the ended flag. */
|
|
9503
|
+
finalize() {
|
|
9504
|
+
this.ended = true;
|
|
9505
|
+
const finalAttrs = this.mergeAttributes(this.attributes);
|
|
9506
|
+
for (const [k, v] of Object.entries(finalAttrs)) {
|
|
9507
|
+
if (v !== void 0) {
|
|
9508
|
+
this.otSpan.setAttribute(k, v);
|
|
9509
|
+
}
|
|
9510
|
+
}
|
|
9511
|
+
this.otSpan.setAttribute("durationMs", Date.now() - this.startTime);
|
|
9512
|
+
this.otSpan.end();
|
|
9513
|
+
}
|
|
9514
|
+
};
|
|
9515
|
+
var NoopSpanContext = class {
|
|
9516
|
+
startTime = Date.now();
|
|
9517
|
+
eventName;
|
|
9518
|
+
attributes;
|
|
9519
|
+
requestId;
|
|
9520
|
+
constructor(eventName, initialAttributes) {
|
|
9521
|
+
this.eventName = eventName;
|
|
9522
|
+
this.attributes = { ...initialAttributes ?? {} };
|
|
9523
|
+
this.requestId = this.attributes.requestId ?? import_common16.CorrelationService.createCorrelationContext();
|
|
9524
|
+
this.attributes.requestId = this.requestId;
|
|
9525
|
+
}
|
|
9526
|
+
getRequestId() {
|
|
9527
|
+
return this.requestId;
|
|
9528
|
+
}
|
|
9529
|
+
addAttributes(extra) {
|
|
9530
|
+
for (const [k, v] of Object.entries(extra)) {
|
|
9531
|
+
if (v !== void 0) {
|
|
9532
|
+
this.attributes[k] = v;
|
|
9533
|
+
}
|
|
9534
|
+
}
|
|
9535
|
+
}
|
|
9536
|
+
end() {
|
|
9537
|
+
}
|
|
9538
|
+
error() {
|
|
9539
|
+
}
|
|
9540
|
+
};
|
|
9541
|
+
|
|
9542
|
+
// src/telemetry/index.ts
|
|
9543
|
+
var singleton;
|
|
9544
|
+
function getTelemetry(options) {
|
|
9545
|
+
if (!singleton) {
|
|
9546
|
+
singleton = new TelemetryService(options);
|
|
9547
|
+
}
|
|
9548
|
+
return singleton;
|
|
9549
|
+
}
|
|
9550
|
+
|
|
9551
|
+
// src/services/getToken.ts
|
|
9552
|
+
async function getToken(env, scopes, clientId) {
|
|
9553
|
+
let provider = null;
|
|
9554
|
+
const options = {
|
|
9555
|
+
uamiClientId: clientId,
|
|
9556
|
+
scopes
|
|
9557
|
+
};
|
|
9558
|
+
if (clientId) {
|
|
9559
|
+
provider = TokenProviderFactory.createProvider(env, "managed_identity" /* ManagedIdentity */, options);
|
|
9560
|
+
} else {
|
|
9561
|
+
provider = TokenProviderFactory.createProvider(env, "msal_cache" /* MsalCache */, options);
|
|
9562
|
+
}
|
|
9563
|
+
const token = await provider.getAccessToken();
|
|
9564
|
+
stampTenantTelemetry(token);
|
|
9565
|
+
return token;
|
|
9566
|
+
}
|
|
9567
|
+
function stampTenantTelemetry(token) {
|
|
9568
|
+
try {
|
|
9569
|
+
const tenantId = (0, import_common17.extractTenantId)(token);
|
|
9570
|
+
getTelemetry().setSharedProperty("tenantId", tenantId || "");
|
|
9571
|
+
} catch {
|
|
9572
|
+
}
|
|
9573
|
+
}
|
|
9574
|
+
|
|
9575
|
+
// src/client/jobs/index.ts
|
|
9576
|
+
init_cjs_shims();
|
|
9577
|
+
var import_common19 = __toESM(require_src());
|
|
9578
|
+
|
|
9579
|
+
// src/utils/headerBuilder.ts
|
|
9580
|
+
init_cjs_shims();
|
|
9581
|
+
var import_common18 = __toESM(require_src());
|
|
9582
|
+
function buildApiHeaders(token, requestId, extra) {
|
|
9583
|
+
const base = {};
|
|
9584
|
+
if (requestId) {
|
|
9585
|
+
base[import_common18.HTTP_HEADER.REQUEST_ID] = requestId;
|
|
9586
|
+
}
|
|
9587
|
+
if (!extra || !(import_common18.HTTP_HEADER.CONTENT_TYPE in extra)) {
|
|
9588
|
+
base[import_common18.HTTP_HEADER.CONTENT_TYPE] = import_common18.HTTP_HEADER.APPLICATION_JSON;
|
|
9589
|
+
}
|
|
9590
|
+
if (token) {
|
|
9591
|
+
base[import_common18.HTTP_HEADER.AUTHORIZATION] = `${import_common18.HTTP_HEADER.BEARER_PREFIX}${token}`;
|
|
9592
|
+
}
|
|
9593
|
+
const merged = { ...base, ...extra || {} };
|
|
9594
|
+
return Object.fromEntries(
|
|
9595
|
+
Object.entries(merged).filter((entry) => entry[1] !== void 0)
|
|
9596
|
+
);
|
|
9597
|
+
}
|
|
9598
|
+
|
|
9599
|
+
// src/utils/noopTelemetry.ts
|
|
9600
|
+
init_cjs_shims();
|
|
9601
|
+
var noopSpan = {
|
|
9602
|
+
addAttributes: () => {
|
|
9603
|
+
},
|
|
9604
|
+
end: () => {
|
|
9605
|
+
},
|
|
9606
|
+
error: () => {
|
|
9607
|
+
}
|
|
9608
|
+
};
|
|
9609
|
+
var noopTelemetry = {
|
|
9610
|
+
span: () => noopSpan
|
|
9611
|
+
};
|
|
9612
|
+
|
|
9613
|
+
// src/client/jobs/index.ts
|
|
9614
|
+
function createJobApiClient(env, region) {
|
|
9615
|
+
const requestService = new import_common19.RequestService(noopTelemetry, buildApiHeaders);
|
|
9616
|
+
return new import_common19.JobApiClient({
|
|
9617
|
+
requestService,
|
|
9618
|
+
baseUrl: env.regions[region].gatewayEndpoint
|
|
9619
|
+
});
|
|
9620
|
+
}
|
|
9621
|
+
|
|
9622
|
+
// src/utils/parseRegion.ts
|
|
9623
|
+
init_cjs_shims();
|
|
9624
|
+
var import_common20 = __toESM(require_src());
|
|
9625
|
+
function parseRegion(value) {
|
|
9626
|
+
if (Object.values(import_common20.Region).includes(value)) {
|
|
9627
|
+
return value;
|
|
9628
|
+
}
|
|
9629
|
+
throw new Error(`Invalid region "${value}". Valid regions: ${Object.values(import_common20.Region).join(", ")}`);
|
|
9630
|
+
}
|
|
9631
|
+
|
|
9632
|
+
// src/commands/jobs/jobDelete.ts
|
|
9633
|
+
function addJobDeleteCommand(jobCommand) {
|
|
9634
|
+
jobCommand.command("delete <jobName>").description("Delete a scheduled job").option("-r, --region <region>", "Target region (default: global)", import_common21.Region.Global).action(async (jobName, options) => {
|
|
9635
|
+
try {
|
|
9636
|
+
const apiEnv4 = (0, import_common21.getApiEnv)(import_common21.SecurityPlatformEnvironment.Production);
|
|
9637
|
+
const accessToken = await getToken(apiEnv4);
|
|
9638
|
+
const region = parseRegion(options.region);
|
|
9639
|
+
const jobApiClient = createJobApiClient(apiEnv4, region);
|
|
9640
|
+
const jobService = new JobService(jobApiClient);
|
|
9641
|
+
await deleteJob(jobService, accessToken, jobName);
|
|
9642
|
+
console.log(`Job "${jobName}" deleted successfully.`);
|
|
9643
|
+
} catch (error) {
|
|
9644
|
+
handleApiError("deleting job", error);
|
|
9645
|
+
}
|
|
9646
|
+
});
|
|
9647
|
+
}
|
|
9648
|
+
|
|
9649
|
+
// src/commands/jobs/jobDisable.ts
|
|
9650
|
+
init_cjs_shims();
|
|
9651
|
+
var import_common22 = __toESM(require_src());
|
|
9652
|
+
function addJobDisableCommand(jobCommand) {
|
|
9653
|
+
jobCommand.command("disable <jobName>").description("Disable a scheduled job").option("-r, --region <region>", "Target region (default: global)", import_common22.Region.Global).action(async (jobName, options) => {
|
|
9654
|
+
try {
|
|
9655
|
+
const apiEnv4 = (0, import_common22.getApiEnv)(import_common22.SecurityPlatformEnvironment.Production);
|
|
9656
|
+
const accessToken = await getToken(apiEnv4);
|
|
9657
|
+
const region = parseRegion(options.region);
|
|
9658
|
+
const jobApiClient = createJobApiClient(apiEnv4, region);
|
|
9659
|
+
const jobService = new JobService(jobApiClient);
|
|
9660
|
+
await disableJob(jobService, accessToken, jobName);
|
|
9661
|
+
console.log(`Job "${jobName}" disabled successfully.`);
|
|
9662
|
+
} catch (error) {
|
|
9663
|
+
handleApiError("disabling job", error);
|
|
9664
|
+
}
|
|
9665
|
+
});
|
|
9666
|
+
}
|
|
9667
|
+
|
|
9668
|
+
// src/commands/jobs/jobDownload.ts
|
|
9669
|
+
init_cjs_shims();
|
|
9670
|
+
var import_common23 = __toESM(require_src());
|
|
9671
|
+
function addJobDownloadCommand(jobCommand) {
|
|
9672
|
+
jobCommand.command("download <jobName>").description("Download the notebook of a scheduled job").option("-o, --output <path>", "Output file path (defaults to <jobName>.ipynb)").option("-r, --region <region>", "Target region (default: global)", import_common23.Region.Global).action(async (jobName, options) => {
|
|
9673
|
+
try {
|
|
9674
|
+
const apiEnv4 = (0, import_common23.getApiEnv)(import_common23.SecurityPlatformEnvironment.Production);
|
|
9675
|
+
const accessToken = await getToken(apiEnv4);
|
|
9676
|
+
const region = parseRegion(options.region);
|
|
9677
|
+
const jobApiClient = createJobApiClient(apiEnv4, region);
|
|
9678
|
+
const jobService = new JobService(jobApiClient);
|
|
9679
|
+
const writtenPath = await downloadJob(jobService, accessToken, jobName, options.output);
|
|
9680
|
+
console.log(`Notebook downloaded to: ${writtenPath}`);
|
|
9681
|
+
} catch (error) {
|
|
9682
|
+
handleApiError("downloading job notebook", error);
|
|
9683
|
+
}
|
|
9684
|
+
});
|
|
9685
|
+
}
|
|
9686
|
+
|
|
9687
|
+
// src/commands/jobs/jobEnable.ts
|
|
9688
|
+
init_cjs_shims();
|
|
9689
|
+
var import_common24 = __toESM(require_src());
|
|
9690
|
+
function addJobEnableCommand(jobCommand) {
|
|
9691
|
+
jobCommand.command("enable <jobName>").description("Enable a scheduled job").option("-r, --region <region>", "Target region (default: global)", import_common24.Region.Global).action(async (jobName, options) => {
|
|
9692
|
+
try {
|
|
9693
|
+
const apiEnv4 = (0, import_common24.getApiEnv)(import_common24.SecurityPlatformEnvironment.Production);
|
|
9694
|
+
const accessToken = await getToken(apiEnv4);
|
|
9695
|
+
const region = parseRegion(options.region);
|
|
9696
|
+
const jobApiClient = createJobApiClient(apiEnv4, region);
|
|
9697
|
+
const jobService = new JobService(jobApiClient);
|
|
9698
|
+
await enableJob(jobService, accessToken, jobName);
|
|
9699
|
+
console.log(`Job "${jobName}" enabled successfully.`);
|
|
9700
|
+
} catch (error) {
|
|
9701
|
+
handleApiError("enabling job", error);
|
|
9702
|
+
}
|
|
9703
|
+
});
|
|
9704
|
+
}
|
|
9705
|
+
|
|
9706
|
+
// src/commands/jobs/jobList.ts
|
|
9707
|
+
init_cjs_shims();
|
|
9708
|
+
var import_common25 = __toESM(require_src());
|
|
9709
|
+
var JOB_COLUMNS = [
|
|
9710
|
+
{ header: "NAME", key: (j) => j.jobName },
|
|
9711
|
+
{ header: "TYPE", key: (j) => j.jobType },
|
|
9712
|
+
{ header: "DISABLED", key: (j) => String(j.isDisabled) }
|
|
9713
|
+
];
|
|
9714
|
+
function addJobListCommand(jobCommand) {
|
|
9715
|
+
jobCommand.command("list").description("List all scheduled jobs").option("-r, --region <region>", "Target region (default: global)", import_common25.Region.Global).action(async (options) => {
|
|
9716
|
+
try {
|
|
9717
|
+
const apiEnv4 = (0, import_common25.getApiEnv)(import_common25.SecurityPlatformEnvironment.Production);
|
|
9718
|
+
const accessToken = await getToken(apiEnv4);
|
|
9719
|
+
const region = parseRegion(options.region);
|
|
9720
|
+
const jobApiClient = createJobApiClient(apiEnv4, region);
|
|
9721
|
+
const jobService = new JobService(jobApiClient);
|
|
9722
|
+
const jobs = await listJobs(jobService, accessToken);
|
|
9723
|
+
const fmt = new OutputFormatter();
|
|
9724
|
+
fmt.print(jobs, JOB_COLUMNS);
|
|
9725
|
+
} catch (error) {
|
|
9726
|
+
handleApiError("listing jobs", error);
|
|
9727
|
+
}
|
|
9728
|
+
});
|
|
9729
|
+
}
|
|
9730
|
+
|
|
9731
|
+
// src/commands/jobs/jobRunCancel.ts
|
|
9732
|
+
init_cjs_shims();
|
|
9733
|
+
var import_common26 = __toESM(require_src());
|
|
9734
|
+
function addJobRunCancelCommand(runCommand) {
|
|
9735
|
+
runCommand.command("cancel <jobName> <runId>").description("Cancel a specific job run").option("-r, --region <region>", "Target region (default: global)", import_common26.Region.Global).action(async (jobName, runId, options) => {
|
|
9736
|
+
try {
|
|
9737
|
+
const apiEnv4 = (0, import_common26.getApiEnv)(import_common26.SecurityPlatformEnvironment.Production);
|
|
9738
|
+
const accessToken = await getToken(apiEnv4);
|
|
9739
|
+
const region = parseRegion(options.region);
|
|
9740
|
+
const jobApiClient = createJobApiClient(apiEnv4, region);
|
|
9741
|
+
const jobService = new JobService(jobApiClient);
|
|
9742
|
+
await cancelJobRun(jobService, accessToken, jobName, runId);
|
|
9743
|
+
console.log(`Run "${runId}" for job "${jobName}" cancelled successfully.`);
|
|
9744
|
+
} catch (error) {
|
|
9745
|
+
handleApiError("cancelling job run", error);
|
|
9746
|
+
}
|
|
9747
|
+
});
|
|
9748
|
+
}
|
|
9749
|
+
|
|
9750
|
+
// src/commands/jobs/jobRunList.ts
|
|
9751
|
+
init_cjs_shims();
|
|
9752
|
+
var import_common27 = __toESM(require_src());
|
|
9753
|
+
var RUN_COLUMNS = [
|
|
9754
|
+
{ header: "RUN ID", key: (r) => r.jobRunId ?? "" },
|
|
9755
|
+
{ header: "STATUS", key: (r) => r.status ?? "" },
|
|
9756
|
+
{ header: "STARTED", key: (r) => r.startTime ?? "" },
|
|
9757
|
+
{ header: "ENDED", key: (r) => r.endTime ?? "" }
|
|
9758
|
+
];
|
|
9759
|
+
function addJobRunListCommand(runCommand) {
|
|
9760
|
+
runCommand.command("list <jobName>").description("List all runs for a scheduled job").option("-r, --region <region>", "Target region (default: global)", import_common27.Region.Global).action(async (jobName, options) => {
|
|
9761
|
+
try {
|
|
9762
|
+
const apiEnv4 = (0, import_common27.getApiEnv)(import_common27.SecurityPlatformEnvironment.Production);
|
|
9763
|
+
const accessToken = await getToken(apiEnv4);
|
|
9764
|
+
const region = parseRegion(options.region);
|
|
9765
|
+
const jobApiClient = createJobApiClient(apiEnv4, region);
|
|
9766
|
+
const jobService = new JobService(jobApiClient);
|
|
9767
|
+
const runs = await listJobRuns(jobService, accessToken, jobName);
|
|
9768
|
+
const fmt = new OutputFormatter();
|
|
9769
|
+
fmt.print(runs, RUN_COLUMNS);
|
|
9770
|
+
} catch (error) {
|
|
9771
|
+
handleApiError("listing job runs", error);
|
|
9772
|
+
}
|
|
9773
|
+
});
|
|
9774
|
+
}
|
|
9775
|
+
|
|
9776
|
+
// src/commands/jobs/jobRunNotebookDownload.ts
|
|
9777
|
+
init_cjs_shims();
|
|
9778
|
+
var import_common28 = __toESM(require_src());
|
|
9779
|
+
function addJobRunNotebookDownloadCommand(notebookCommand) {
|
|
9780
|
+
notebookCommand.command("download <jobName> <runId>").description("Download the notebook snapshot of a job run").option("-o, --output <path>", "Output file path (defaults to <jobName>_<runId>.ipynb)").option("-r, --region <region>", "Target region (default: global)", import_common28.Region.Global).action(async (jobName, runId, options) => {
|
|
9781
|
+
try {
|
|
9782
|
+
const apiEnv4 = (0, import_common28.getApiEnv)(import_common28.SecurityPlatformEnvironment.Production);
|
|
9783
|
+
const accessToken = await getToken(apiEnv4);
|
|
9784
|
+
const region = parseRegion(options.region);
|
|
9785
|
+
const jobApiClient = createJobApiClient(apiEnv4, region);
|
|
9786
|
+
const jobService = new JobService(jobApiClient);
|
|
9787
|
+
const writtenPath = await downloadJobRunNotebook(jobService, accessToken, jobName, runId, options.output);
|
|
9788
|
+
console.log(`Notebook downloaded to: ${writtenPath}`);
|
|
9789
|
+
} catch (error) {
|
|
9790
|
+
handleApiError("downloading job run notebook", error);
|
|
9791
|
+
}
|
|
9792
|
+
});
|
|
9793
|
+
}
|
|
9794
|
+
|
|
9795
|
+
// src/commands/jobs/jobRunShow.ts
|
|
9796
|
+
init_cjs_shims();
|
|
9797
|
+
var import_common29 = __toESM(require_src());
|
|
9798
|
+
var RUN_DETAIL_COLUMNS = [
|
|
9799
|
+
{ header: "FIELD", key: (f) => f.label },
|
|
9800
|
+
{ header: "VALUE", key: (f) => f.value }
|
|
9801
|
+
];
|
|
9802
|
+
function addJobRunShowCommand(runCommand) {
|
|
9803
|
+
runCommand.command("show <jobName> <runId>").description("Show the details of a job run").option("-r, --region <region>", "Target region (default: global)", import_common29.Region.Global).action(async (jobName, runId, options) => {
|
|
9804
|
+
try {
|
|
9805
|
+
const apiEnv4 = (0, import_common29.getApiEnv)(import_common29.SecurityPlatformEnvironment.Production);
|
|
9806
|
+
const accessToken = await getToken(apiEnv4);
|
|
9807
|
+
const region = parseRegion(options.region);
|
|
9808
|
+
const jobApiClient = createJobApiClient(apiEnv4, region);
|
|
9809
|
+
const jobService = new JobService(jobApiClient);
|
|
9810
|
+
const run = await getJobRun(jobService, accessToken, jobName, runId);
|
|
9811
|
+
printRunDetails(run);
|
|
9812
|
+
} catch (error) {
|
|
9813
|
+
handleApiError("showing job run", error);
|
|
9814
|
+
}
|
|
9815
|
+
});
|
|
9816
|
+
}
|
|
9817
|
+
function printRunDetails(run) {
|
|
9818
|
+
const fields = [
|
|
9819
|
+
{ label: "Run ID", value: run.jobRunId ?? "" },
|
|
9820
|
+
{ label: "Status", value: run.status ?? "" },
|
|
9821
|
+
{ label: "Schedule", value: run.scheduleName ?? "" },
|
|
9822
|
+
{ label: "Started", value: run.startTime ?? "" },
|
|
9823
|
+
{ label: "Ended", value: run.endTime ?? "" },
|
|
9824
|
+
{ label: "Error", value: run.error?.errorMessage ?? "" }
|
|
9825
|
+
];
|
|
9826
|
+
const fmt = new OutputFormatter();
|
|
9827
|
+
fmt.print(fields, RUN_DETAIL_COLUMNS);
|
|
9828
|
+
}
|
|
9829
|
+
|
|
9830
|
+
// src/commands/jobs/jobRunStart.ts
|
|
9831
|
+
init_cjs_shims();
|
|
9832
|
+
var import_common30 = __toESM(require_src());
|
|
9833
|
+
function addJobRunStartCommand(runCommand) {
|
|
9834
|
+
runCommand.command("start <jobName>").description("Start an ad-hoc run of a scheduled job").option("-r, --region <region>", "Target region (default: global)", import_common30.Region.Global).action(async (jobName, options) => {
|
|
9835
|
+
try {
|
|
9836
|
+
const apiEnv4 = (0, import_common30.getApiEnv)(import_common30.SecurityPlatformEnvironment.Production);
|
|
9837
|
+
const accessToken = await getToken(apiEnv4);
|
|
9838
|
+
const region = parseRegion(options.region);
|
|
9839
|
+
const jobApiClient = createJobApiClient(apiEnv4, region);
|
|
9840
|
+
const jobService = new JobService(jobApiClient);
|
|
9841
|
+
const run = await startJobRun(jobService, accessToken, jobName);
|
|
9842
|
+
console.log(`Job run started. Run ID: ${run.jobRunId ?? "(unknown)"}`);
|
|
9843
|
+
} catch (error) {
|
|
9844
|
+
handleApiError("starting job run", error);
|
|
9845
|
+
}
|
|
9846
|
+
});
|
|
9847
|
+
}
|
|
9848
|
+
|
|
9849
|
+
// src/commands/jobs/jobShow.ts
|
|
9850
|
+
init_cjs_shims();
|
|
9851
|
+
var import_common31 = __toESM(require_src());
|
|
9852
|
+
var JOB_DETAIL_COLUMNS = [
|
|
9853
|
+
{ header: "FIELD", key: (f) => f.label },
|
|
9854
|
+
{ header: "VALUE", key: (f) => f.value }
|
|
9855
|
+
];
|
|
9856
|
+
function addJobShowCommand(jobCommand) {
|
|
9857
|
+
jobCommand.command("show <jobName>").description("Show the details of a scheduled job").option("-r, --region <region>", "Target region (default: global)", import_common31.Region.Global).action(async (jobName, options) => {
|
|
9858
|
+
try {
|
|
9859
|
+
const apiEnv4 = (0, import_common31.getApiEnv)(import_common31.SecurityPlatformEnvironment.Production);
|
|
9860
|
+
const accessToken = await getToken(apiEnv4);
|
|
9861
|
+
const region = parseRegion(options.region);
|
|
9862
|
+
const jobApiClient = createJobApiClient(apiEnv4, region);
|
|
9863
|
+
const jobService = new JobService(jobApiClient);
|
|
9864
|
+
const job = await getJob(jobService, accessToken, jobName);
|
|
9865
|
+
printJobDetails(job);
|
|
9866
|
+
} catch (error) {
|
|
9867
|
+
handleApiError("showing job", error);
|
|
9868
|
+
}
|
|
9869
|
+
});
|
|
9870
|
+
}
|
|
9871
|
+
function printJobDetails(job) {
|
|
9872
|
+
const def = job.jobDefinition;
|
|
9873
|
+
const fields = [
|
|
9874
|
+
{ label: "Name", value: def.jobName ?? "" },
|
|
9875
|
+
{ label: "Type", value: def.jobType ?? "" },
|
|
9876
|
+
{ label: "Disabled", value: String(def.isDisabled ?? false) },
|
|
9877
|
+
{ label: "Description", value: def.description ?? "" },
|
|
9878
|
+
{ label: "Spark Pool", value: def.computeInfo?.friendlyName ?? "" },
|
|
9879
|
+
{ label: "Created At", value: def.createdAt ?? "" },
|
|
9880
|
+
{ label: "Last Updated At", value: def.lastUpdatedAt ?? "" }
|
|
9881
|
+
];
|
|
9882
|
+
const fmt = new OutputFormatter();
|
|
9883
|
+
fmt.print(fields, JOB_DETAIL_COLUMNS);
|
|
9884
|
+
}
|
|
9885
|
+
|
|
9886
|
+
// src/commands/lake/database.ts
|
|
9887
|
+
init_cjs_shims();
|
|
9888
|
+
var import_common36 = __toESM(require_src());
|
|
9889
|
+
|
|
9890
|
+
// src/actions/lake/index.ts
|
|
9891
|
+
init_cjs_shims();
|
|
9892
|
+
|
|
9893
|
+
// src/actions/lake/listDatabases.ts
|
|
9894
|
+
init_cjs_shims();
|
|
9895
|
+
var import_common32 = __toESM(require_src());
|
|
9896
|
+
async function listDatabases(databaseService, accessToken) {
|
|
9897
|
+
const requestId = import_common32.CorrelationService.createCorrelationContext();
|
|
9898
|
+
console.info("Fetching databases...");
|
|
9899
|
+
return databaseService.listDatabases(accessToken, requestId);
|
|
9900
|
+
}
|
|
9901
|
+
|
|
9902
|
+
// src/actions/lake/listTables.ts
|
|
9903
|
+
init_cjs_shims();
|
|
9904
|
+
var import_common33 = __toESM(require_src());
|
|
9905
|
+
async function listTables(tableService, accessToken, database) {
|
|
9906
|
+
const requestId = import_common33.CorrelationService.createCorrelationContext();
|
|
9907
|
+
const scope = database ? ` for database "${database.databaseName}"` : "";
|
|
9908
|
+
console.info(`Fetching lake tables${scope}...`);
|
|
9909
|
+
return tableService.listTables(accessToken, requestId, database);
|
|
9910
|
+
}
|
|
9911
|
+
|
|
9912
|
+
// src/services/lake/index.ts
|
|
9913
|
+
init_cjs_shims();
|
|
9914
|
+
|
|
9915
|
+
// src/services/lake/databaseService.ts
|
|
9916
|
+
init_cjs_shims();
|
|
9917
|
+
var DatabaseService = class {
|
|
9918
|
+
constructor(lakeApiClient) {
|
|
9919
|
+
this.lakeApiClient = lakeApiClient;
|
|
9920
|
+
}
|
|
9921
|
+
async listDatabases(accessToken, requestId) {
|
|
9922
|
+
return this.lakeApiClient.fetchDatabases(accessToken, requestId);
|
|
9923
|
+
}
|
|
9924
|
+
};
|
|
9925
|
+
|
|
9926
|
+
// src/services/lake/tableService.ts
|
|
9927
|
+
init_cjs_shims();
|
|
9928
|
+
var TableService = class {
|
|
9929
|
+
constructor(lakeApiClient) {
|
|
9930
|
+
this.lakeApiClient = lakeApiClient;
|
|
9931
|
+
}
|
|
9932
|
+
async listTables(accessToken, requestId, database) {
|
|
9933
|
+
return this.lakeApiClient.fetchLakeTables(accessToken, requestId, database);
|
|
9934
|
+
}
|
|
9935
|
+
};
|
|
9936
|
+
|
|
9937
|
+
// src/services/lake/databaseLookup.ts
|
|
9938
|
+
init_cjs_shims();
|
|
9939
|
+
var SYSTEM_TABLES_DISPLAY_NAME = "System tables";
|
|
9940
|
+
var DEFAULT_DATABASE = { databaseName: "default" };
|
|
9941
|
+
async function lookupDatabase(options, lakeApiClient, accessToken) {
|
|
9942
|
+
if (options.databaseId) {
|
|
9943
|
+
if (options.databaseId === SYSTEM_TABLES_DISPLAY_NAME) {
|
|
9944
|
+
return DEFAULT_DATABASE;
|
|
9945
|
+
}
|
|
9946
|
+
return lookupDatabaseById(options.databaseId, lakeApiClient, accessToken);
|
|
9947
|
+
}
|
|
9948
|
+
if (options.databaseName) {
|
|
9949
|
+
if (options.databaseName === SYSTEM_TABLES_DISPLAY_NAME) {
|
|
9950
|
+
return DEFAULT_DATABASE;
|
|
9951
|
+
}
|
|
9952
|
+
return lookupDatabaseByName(options.databaseName, lakeApiClient, accessToken);
|
|
9953
|
+
}
|
|
9954
|
+
return void 0;
|
|
9955
|
+
}
|
|
9956
|
+
async function lookupDatabaseById(databaseId, lakeApiClient, accessToken) {
|
|
9957
|
+
const databaseService = new DatabaseService(lakeApiClient);
|
|
9958
|
+
const databases = await listDatabases(databaseService, accessToken);
|
|
9959
|
+
const match = databases.find((db) => db.databaseName === databaseId);
|
|
9960
|
+
if (!match) {
|
|
9961
|
+
console.error(
|
|
9962
|
+
`Error: database "${databaseId}" not found. Run "sentinel database list" to see available databases.`
|
|
9963
|
+
);
|
|
9964
|
+
process.exit(1);
|
|
9965
|
+
}
|
|
9966
|
+
return match;
|
|
9967
|
+
}
|
|
9968
|
+
async function lookupDatabaseByName(databaseName, lakeApiClient, accessToken) {
|
|
9969
|
+
const databaseService = new DatabaseService(lakeApiClient);
|
|
9970
|
+
const databases = await listDatabases(databaseService, accessToken);
|
|
9971
|
+
const match = databases.find((db) => db.sentinelWorkspace?.name === databaseName);
|
|
9972
|
+
if (!match) {
|
|
9973
|
+
console.error(
|
|
9974
|
+
`Error: database "${databaseName}" not found. Run "sentinel database list" to see available databases.`
|
|
9975
|
+
);
|
|
9976
|
+
process.exit(1);
|
|
9977
|
+
}
|
|
9978
|
+
return match;
|
|
9979
|
+
}
|
|
9980
|
+
|
|
9981
|
+
// src/client/lake/index.ts
|
|
9982
|
+
init_cjs_shims();
|
|
9983
|
+
var import_common34 = __toESM(require_src());
|
|
9984
|
+
function createLakeApiClient(env) {
|
|
9985
|
+
const requestService = new import_common34.RequestService(noopTelemetry, buildApiHeaders);
|
|
9986
|
+
return new import_common34.LakeApiClient({
|
|
9987
|
+
requestService,
|
|
9988
|
+
telemetry: noopTelemetry,
|
|
9989
|
+
baseUrl: env.gatewayEndpoint
|
|
9990
|
+
});
|
|
9991
|
+
}
|
|
9992
|
+
|
|
9993
|
+
// src/telemetry/events.ts
|
|
9994
|
+
init_cjs_shims();
|
|
9995
|
+
var CliEvents = {
|
|
9996
|
+
/** Fired exactly once per CLI process, before Commander parses argv. */
|
|
9997
|
+
Invoked: "cli.invoked",
|
|
9998
|
+
// Top-level commands
|
|
9999
|
+
Login: "cli.login",
|
|
10000
|
+
Logout: "cli.logout",
|
|
10001
|
+
Token: "cli.token",
|
|
10002
|
+
Update: "cli.update",
|
|
10003
|
+
// `package` group
|
|
10004
|
+
PackageCreateZip: "cli.package.createzip",
|
|
10005
|
+
PackageValidate: "cli.package.validate",
|
|
10006
|
+
// `job` group
|
|
10007
|
+
JobPublish: "cli.job.publish",
|
|
10008
|
+
// `database` group
|
|
10009
|
+
DatabaseList: "cli.database.list",
|
|
10010
|
+
// `table` group
|
|
10011
|
+
TableList: "cli.table.list",
|
|
10012
|
+
TableShow: "cli.table.show"
|
|
10013
|
+
};
|
|
10014
|
+
|
|
10015
|
+
// src/telemetry/withCommandSpan.ts
|
|
10016
|
+
init_cjs_shims();
|
|
10017
|
+
|
|
10018
|
+
// src/telemetry/commandInterceptor.ts
|
|
10019
|
+
init_cjs_shims();
|
|
10020
|
+
var ATTACHED_FLAG = /* @__PURE__ */ Symbol.for("sentinel.cli.commandTelemetryAttached");
|
|
10021
|
+
function buildCommandPath(cmd) {
|
|
10022
|
+
const segments = [];
|
|
10023
|
+
let cursor = cmd;
|
|
10024
|
+
while (cursor) {
|
|
10025
|
+
segments.unshift(cursor.name());
|
|
10026
|
+
cursor = cursor.parent ?? null;
|
|
10027
|
+
}
|
|
10028
|
+
segments.shift();
|
|
10029
|
+
return segments.join(".");
|
|
10030
|
+
}
|
|
10031
|
+
function buildCommandInvokedAttributes(cmd) {
|
|
10032
|
+
const path8 = buildCommandPath(cmd);
|
|
10033
|
+
const segments = path8.split(".");
|
|
10034
|
+
const command = segments[0];
|
|
10035
|
+
const subcommand = segments.length > 1 ? segments[segments.length - 1] : "";
|
|
10036
|
+
return {
|
|
10037
|
+
command,
|
|
10038
|
+
subcommand,
|
|
10039
|
+
commandPath: path8
|
|
10040
|
+
};
|
|
10041
|
+
}
|
|
10042
|
+
function attachCommandTelemetry(program2, telemetry2) {
|
|
10043
|
+
const flagged = program2;
|
|
10044
|
+
if (flagged[ATTACHED_FLAG]) {
|
|
10045
|
+
return;
|
|
10046
|
+
}
|
|
10047
|
+
flagged[ATTACHED_FLAG] = true;
|
|
10048
|
+
program2.hook("preAction", (_thisCommand, actionCommand) => {
|
|
10049
|
+
try {
|
|
10050
|
+
const attrs = buildCommandInvokedAttributes(actionCommand);
|
|
10051
|
+
telemetry2.event("Command.Invoked", { properties: attrs });
|
|
10052
|
+
} catch {
|
|
10053
|
+
}
|
|
10054
|
+
});
|
|
10055
|
+
}
|
|
10056
|
+
|
|
10057
|
+
// src/telemetry/errorContext.ts
|
|
10058
|
+
init_cjs_shims();
|
|
10059
|
+
var import_common35 = __toESM(require_src());
|
|
10060
|
+
function isObject(v) {
|
|
10061
|
+
return typeof v === "object" && v !== null;
|
|
10062
|
+
}
|
|
10063
|
+
function extractErrorProperties(error) {
|
|
10064
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
10065
|
+
const redacted = redactError(err);
|
|
10066
|
+
const props = {
|
|
10067
|
+
errorName: redacted.errorName,
|
|
10068
|
+
errorMessage: redacted.errorMessage,
|
|
10069
|
+
errorStack: redacted.errorStack,
|
|
10070
|
+
isException: "true"
|
|
10071
|
+
};
|
|
10072
|
+
if (!isObject(error)) {
|
|
10073
|
+
return props;
|
|
10074
|
+
}
|
|
10075
|
+
const axiosErr = error;
|
|
10076
|
+
if (!axiosErr.response) {
|
|
10077
|
+
return props;
|
|
10078
|
+
}
|
|
10079
|
+
props.status = axiosErr.response.status !== void 0 ? String(axiosErr.response.status) : "unknown";
|
|
10080
|
+
const method = axiosErr.config?.method;
|
|
10081
|
+
props.method = typeof method === "string" ? method.toUpperCase() : "unknown";
|
|
10082
|
+
const url = axiosErr.config?.url;
|
|
10083
|
+
props.url = typeof url === "string" ? url : "unknown";
|
|
10084
|
+
const correlationId = import_common35.CorrelationService.extractCorrelationId(axiosErr.response);
|
|
10085
|
+
if (correlationId) {
|
|
10086
|
+
props.correlationId = correlationId;
|
|
10087
|
+
}
|
|
10088
|
+
return props;
|
|
10089
|
+
}
|
|
10090
|
+
function toTelemetryProperties(props) {
|
|
10091
|
+
const out = {
|
|
10092
|
+
errorName: props.errorName,
|
|
10093
|
+
errorMessage: props.errorMessage,
|
|
10094
|
+
errorStack: props.errorStack,
|
|
10095
|
+
isException: props.isException
|
|
10096
|
+
};
|
|
10097
|
+
if (props.status !== void 0) {
|
|
10098
|
+
out.status = props.status;
|
|
10099
|
+
}
|
|
10100
|
+
if (props.method !== void 0) {
|
|
10101
|
+
out.method = props.method;
|
|
10102
|
+
}
|
|
10103
|
+
if (props.url !== void 0) {
|
|
10104
|
+
out.url = props.url;
|
|
10105
|
+
}
|
|
10106
|
+
if (props.correlationId !== void 0) {
|
|
10107
|
+
out.correlationId = props.correlationId;
|
|
10108
|
+
}
|
|
10109
|
+
return out;
|
|
10110
|
+
}
|
|
10111
|
+
|
|
10112
|
+
// src/telemetry/withCommandSpan.ts
|
|
10113
|
+
function withCommandSpan(eventName, handler, telemetry2) {
|
|
10114
|
+
return async (...args) => {
|
|
10115
|
+
let span;
|
|
10116
|
+
try {
|
|
10117
|
+
const command = extractCommand(args);
|
|
10118
|
+
const initialAttributes = command ? buildCommandInvokedAttributes(command) : void 0;
|
|
10119
|
+
const svc = telemetry2 ?? getTelemetry();
|
|
10120
|
+
span = svc.span(eventName, initialAttributes);
|
|
10121
|
+
} catch {
|
|
10122
|
+
span = void 0;
|
|
10123
|
+
}
|
|
10124
|
+
let success = true;
|
|
10125
|
+
try {
|
|
10126
|
+
await handler(...args);
|
|
10127
|
+
} catch (err) {
|
|
10128
|
+
success = false;
|
|
10129
|
+
const props = extractErrorProperties(err);
|
|
10130
|
+
safeError(span, err, toTelemetryProperties(props));
|
|
10131
|
+
throw err;
|
|
10132
|
+
} finally {
|
|
10133
|
+
safeAddAttributes(span, { success });
|
|
10134
|
+
safeEnd(span);
|
|
10135
|
+
}
|
|
10136
|
+
};
|
|
10137
|
+
}
|
|
10138
|
+
function extractCommand(args) {
|
|
10139
|
+
const last = args[args.length - 1];
|
|
10140
|
+
if (last && typeof last === "object" && typeof last.name === "function") {
|
|
10141
|
+
return last;
|
|
10142
|
+
}
|
|
10143
|
+
return void 0;
|
|
10144
|
+
}
|
|
10145
|
+
function safeAddAttributes(span, extra) {
|
|
10146
|
+
if (!span) {
|
|
10147
|
+
return;
|
|
10148
|
+
}
|
|
10149
|
+
try {
|
|
10150
|
+
span.addAttributes(extra);
|
|
10151
|
+
} catch {
|
|
10152
|
+
}
|
|
10153
|
+
}
|
|
10154
|
+
function safeEnd(span, extra) {
|
|
10155
|
+
if (!span) {
|
|
10156
|
+
return;
|
|
10157
|
+
}
|
|
10158
|
+
try {
|
|
10159
|
+
span.end(extra);
|
|
10160
|
+
} catch {
|
|
10161
|
+
}
|
|
10162
|
+
}
|
|
10163
|
+
function safeError(span, err, extra) {
|
|
10164
|
+
if (!span) {
|
|
10165
|
+
return;
|
|
10166
|
+
}
|
|
10167
|
+
try {
|
|
10168
|
+
span.error(err instanceof Error ? err : new Error(String(err)), extra);
|
|
10169
|
+
} catch {
|
|
10170
|
+
}
|
|
10171
|
+
}
|
|
10172
|
+
|
|
10173
|
+
// src/commands/lake/database.ts
|
|
10174
|
+
function addDatabaseCommand(databaseCommand) {
|
|
10175
|
+
databaseCommand.command("list").description("List all available databases").action(
|
|
10176
|
+
withCommandSpan(CliEvents.DatabaseList, async () => {
|
|
10177
|
+
try {
|
|
10178
|
+
const apiEnv4 = (0, import_common36.getApiEnv)(import_common36.SecurityPlatformEnvironment.Production);
|
|
10179
|
+
const accessToken = await getToken(apiEnv4);
|
|
10180
|
+
const lakeApiClient = createLakeApiClient(apiEnv4);
|
|
10181
|
+
const databaseService = new DatabaseService(lakeApiClient);
|
|
10182
|
+
const databases = await listDatabases(databaseService, accessToken);
|
|
10183
|
+
const fmt = new OutputFormatter();
|
|
10184
|
+
fmt.print(databases, [
|
|
10185
|
+
{ header: "ID", key: (db) => db.databaseName === "default" ? "System tables" : db.databaseName },
|
|
10186
|
+
{
|
|
10187
|
+
header: "NAME",
|
|
10188
|
+
key: (db) => db.databaseName === "default" ? "System tables" : db.sentinelWorkspace?.name ?? ""
|
|
10189
|
+
}
|
|
10190
|
+
]);
|
|
10191
|
+
} catch (error) {
|
|
10192
|
+
handleApiError("listing databases", error);
|
|
10193
|
+
}
|
|
10194
|
+
})
|
|
10195
|
+
);
|
|
10196
|
+
}
|
|
10197
|
+
|
|
10198
|
+
// src/commands/lake/lakeTables.ts
|
|
10199
|
+
init_cjs_shims();
|
|
10200
|
+
var import_common37 = __toESM(require_src());
|
|
10201
|
+
var TABLE_COLUMNS = [
|
|
10202
|
+
{ header: "TABLE", key: (t) => t.name ?? "" },
|
|
10203
|
+
{
|
|
10204
|
+
header: "DATABASE NAME",
|
|
10205
|
+
key: (t) => t.sgWorkspaceName === "default" ? SYSTEM_TABLES_DISPLAY_NAME : t.sgWorkspaceName ?? ""
|
|
10206
|
+
},
|
|
10207
|
+
{ header: "CATEGORY", key: (t) => t.category ?? "" }
|
|
10208
|
+
];
|
|
10209
|
+
function addLakeTableListCommand(tableCommand) {
|
|
10210
|
+
tableCommand.command("list").description("List lake tables").option("--database-id <databaseId>", "Database ID to fetch tables").option("--database-name <databaseName>", "Database name to fetch tables").action(
|
|
10211
|
+
withCommandSpan(CliEvents.TableList, async (options) => {
|
|
10212
|
+
try {
|
|
10213
|
+
validateOptions(options);
|
|
10214
|
+
const apiEnv4 = (0, import_common37.getApiEnv)(import_common37.SecurityPlatformEnvironment.Production);
|
|
10215
|
+
const accessToken = await getToken(apiEnv4);
|
|
10216
|
+
const lakeApiClient = createLakeApiClient(apiEnv4);
|
|
10217
|
+
const database = await lookupDatabase(options, lakeApiClient, accessToken);
|
|
10218
|
+
const tableService = new TableService(lakeApiClient);
|
|
10219
|
+
const tables = await listTables(tableService, accessToken, database);
|
|
10220
|
+
printTables(tables);
|
|
10221
|
+
} catch (error) {
|
|
10222
|
+
handleApiError("listing lake tables", error);
|
|
10223
|
+
}
|
|
10224
|
+
})
|
|
10225
|
+
);
|
|
10226
|
+
}
|
|
10227
|
+
function validateOptions(options) {
|
|
10228
|
+
if (options.databaseId && options.databaseName) {
|
|
10229
|
+
throw new Error("--database-id and --database-name are mutually exclusive. Provide only one.");
|
|
7513
10230
|
}
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
10231
|
+
}
|
|
10232
|
+
function printTables(tables) {
|
|
10233
|
+
const fmt = new OutputFormatter();
|
|
10234
|
+
fmt.print(tables, TABLE_COLUMNS);
|
|
10235
|
+
}
|
|
10236
|
+
|
|
10237
|
+
// src/commands/lake/lakeTableSchema.ts
|
|
10238
|
+
init_cjs_shims();
|
|
10239
|
+
var import_common38 = __toESM(require_src());
|
|
10240
|
+
var SCHEMA_COLUMNS = [
|
|
10241
|
+
{ header: "COLUMN", key: (col) => col.name },
|
|
10242
|
+
{ header: "TYPE", key: (col) => col.type }
|
|
10243
|
+
];
|
|
10244
|
+
function addLakeTableShowCommand(tableCommand) {
|
|
10245
|
+
tableCommand.command("show <tableName>").description("Show the schema of a lake table").option("--database-id <databaseId>", "Database ID to look up the table in").option("--database-name <databaseName>", "Database name to look up the table in").action(
|
|
10246
|
+
withCommandSpan(CliEvents.TableShow, async (tableName, options) => {
|
|
7517
10247
|
try {
|
|
7518
|
-
|
|
7519
|
-
const
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
|
|
7525
|
-
|
|
10248
|
+
validateOptions2(options);
|
|
10249
|
+
const apiEnv4 = (0, import_common38.getApiEnv)(import_common38.SecurityPlatformEnvironment.Production);
|
|
10250
|
+
const accessToken = await getToken(apiEnv4);
|
|
10251
|
+
const lakeApiClient = createLakeApiClient(apiEnv4);
|
|
10252
|
+
const database = await lookupDatabase(options, lakeApiClient, accessToken) ?? DEFAULT_DATABASE;
|
|
10253
|
+
const tableService = new TableService(lakeApiClient);
|
|
10254
|
+
const tables = await listTables(tableService, accessToken, database);
|
|
10255
|
+
const table = findTable(tables, tableName);
|
|
10256
|
+
if (!table) {
|
|
10257
|
+
console.error(
|
|
10258
|
+
`Error: table "${tableName}" not found. Run "sentinel table list" to see available tables.`
|
|
10259
|
+
);
|
|
10260
|
+
throw new Error(`Table not found: ${tableName}`);
|
|
7526
10261
|
}
|
|
7527
|
-
|
|
7528
|
-
|
|
10262
|
+
printSchema(table);
|
|
10263
|
+
} catch (error) {
|
|
10264
|
+
handleApiError("showing lake table schema", error);
|
|
7529
10265
|
}
|
|
7530
|
-
}
|
|
10266
|
+
})
|
|
10267
|
+
);
|
|
10268
|
+
}
|
|
10269
|
+
function validateOptions2(options) {
|
|
10270
|
+
if (options.databaseId && options.databaseName) {
|
|
10271
|
+
throw new Error("--database-id and --database-name are mutually exclusive. Provide only one.");
|
|
7531
10272
|
}
|
|
7532
|
-
|
|
10273
|
+
}
|
|
10274
|
+
function findTable(tables, tableName) {
|
|
10275
|
+
const lowerName = tableName.toLowerCase();
|
|
10276
|
+
return tables.find((t) => t.name?.toLowerCase() === lowerName);
|
|
10277
|
+
}
|
|
10278
|
+
function printSchema(table) {
|
|
10279
|
+
const fmt = new OutputFormatter();
|
|
10280
|
+
fmt.print(table.schema, SCHEMA_COLUMNS);
|
|
10281
|
+
}
|
|
10282
|
+
|
|
10283
|
+
// src/commands/login.ts
|
|
10284
|
+
init_cjs_shims();
|
|
10285
|
+
var os5 = __toESM(require("os"));
|
|
10286
|
+
|
|
10287
|
+
// src/actions/authCodeLogin.ts
|
|
10288
|
+
init_cjs_shims();
|
|
10289
|
+
var import_child_process = require("child_process");
|
|
10290
|
+
var import_common39 = __toESM(require_src());
|
|
10291
|
+
var apiEnv3 = (0, import_common39.getApiEnv)(import_common39.SecurityPlatformEnvironment.Production);
|
|
10292
|
+
function openSystemBrowser(url) {
|
|
10293
|
+
return new Promise((resolve2, reject) => {
|
|
10294
|
+
const command = process.platform === "darwin" ? "open" : "xdg-open";
|
|
10295
|
+
(0, import_child_process.execFile)(command, [url], (error) => {
|
|
10296
|
+
if (error) {
|
|
10297
|
+
reject(new Error(`Failed to open browser: ${error.message}`));
|
|
10298
|
+
} else {
|
|
10299
|
+
resolve2();
|
|
10300
|
+
}
|
|
10301
|
+
});
|
|
10302
|
+
});
|
|
10303
|
+
}
|
|
10304
|
+
async function browserAuthLogin(scopes, tenant) {
|
|
10305
|
+
const authorityOverride = tenant ? `${new URL(apiEnv3.aadEndpoint).origin}/${encodeURIComponent(tenant)}` : void 0;
|
|
10306
|
+
const authority = authorityOverride ?? apiEnv3.aadEndpoint;
|
|
10307
|
+
const msalInstance = await getMsalInstance(apiEnv3, authorityOverride);
|
|
10308
|
+
console.log("\u{1F510} Starting browser login. A browser window will open.");
|
|
10309
|
+
const result = await msalInstance.acquireTokenInteractive({
|
|
10310
|
+
scopes,
|
|
10311
|
+
prompt: "select_account",
|
|
10312
|
+
openBrowser: openSystemBrowser,
|
|
10313
|
+
successTemplate: "<h1>Authentication successful</h1><p>You may close this tab and return to the terminal.</p>",
|
|
10314
|
+
errorTemplate: "<h1>Authentication failed</h1><p>{error}</p>"
|
|
10315
|
+
});
|
|
10316
|
+
if (!result?.accessToken) {
|
|
10317
|
+
throw new Error("Token acquisition failed: received null or empty token.");
|
|
10318
|
+
}
|
|
10319
|
+
if (result.account) {
|
|
10320
|
+
saveBrokerAccount(result.account, authority);
|
|
10321
|
+
}
|
|
10322
|
+
console.log("\u{1F511} Token acquired successfully.");
|
|
10323
|
+
return result.accessToken;
|
|
7533
10324
|
}
|
|
7534
10325
|
|
|
7535
10326
|
// src/actions/deviceCodeLogin.ts
|
|
10327
|
+
init_cjs_shims();
|
|
7536
10328
|
async function login(scopes) {
|
|
7537
10329
|
await loginAndGetDeviceCodeToken(scopes);
|
|
7538
10330
|
}
|
|
7539
10331
|
|
|
7540
10332
|
// src/actions/managedIdentityLogin.ts
|
|
7541
10333
|
init_cjs_shims();
|
|
7542
|
-
var
|
|
10334
|
+
var import_identity3 = require("@azure/identity");
|
|
7543
10335
|
async function getTokenManagedIdentity(options) {
|
|
7544
10336
|
const { scope, clientId, objectId, resourceId, workload } = options;
|
|
7545
10337
|
let credential;
|
|
7546
10338
|
try {
|
|
7547
10339
|
if (workload) {
|
|
7548
10340
|
console.log("\u{1F510} Using WorkloadIdentityCredential...");
|
|
7549
|
-
credential = new
|
|
10341
|
+
credential = new import_identity3.WorkloadIdentityCredential();
|
|
7550
10342
|
} else if (clientId) {
|
|
7551
10343
|
console.log("\u{1F510} Using ManagedIdentityCredential with Client ID...");
|
|
7552
|
-
credential = new
|
|
10344
|
+
credential = new import_identity3.ManagedIdentityCredential(clientId);
|
|
7553
10345
|
} else if (objectId) {
|
|
7554
10346
|
console.log("\u{1F510} Using ManagedIdentityCredential with Object ID...");
|
|
7555
|
-
credential = new
|
|
10347
|
+
credential = new import_identity3.ManagedIdentityCredential({ objectId });
|
|
7556
10348
|
} else if (resourceId) {
|
|
7557
10349
|
console.log("\u{1F510} Using ManagedIdentityCredential with Resource ID...");
|
|
7558
|
-
credential = new
|
|
10350
|
+
credential = new import_identity3.ManagedIdentityCredential({ resourceId });
|
|
7559
10351
|
} else {
|
|
7560
10352
|
throw new Error("No managed identity parameters provided.");
|
|
7561
10353
|
}
|
|
@@ -7627,7 +10419,7 @@ function loginCommand(program2) {
|
|
|
7627
10419
|
console.log("\u2705 Logged in via Windows Native Broker.");
|
|
7628
10420
|
} else {
|
|
7629
10421
|
console.log("\u{1F310} Launching Browser Authentication (Auth Code Flow)...");
|
|
7630
|
-
await browserAuthLogin(scope);
|
|
10422
|
+
await browserAuthLogin(scope, tenant);
|
|
7631
10423
|
console.log("\u2705 Logged in using Browser Authentication.");
|
|
7632
10424
|
}
|
|
7633
10425
|
} catch (error) {
|
|
@@ -7657,215 +10449,244 @@ function logoutCommand(program2) {
|
|
|
7657
10449
|
|
|
7658
10450
|
// src/commands/publishJob.ts
|
|
7659
10451
|
init_cjs_shims();
|
|
7660
|
-
var
|
|
7661
|
-
var
|
|
10452
|
+
var import_common41 = __toESM(require_src());
|
|
10453
|
+
var import_path6 = __toESM(require("path"));
|
|
7662
10454
|
|
|
7663
10455
|
// src/actions/publishJob.ts
|
|
7664
10456
|
init_cjs_shims();
|
|
7665
|
-
var
|
|
7666
|
-
var
|
|
7667
|
-
var
|
|
7668
|
-
var
|
|
10457
|
+
var import_common40 = __toESM(require_src());
|
|
10458
|
+
var fs6 = __toESM(require("fs"));
|
|
10459
|
+
var import_path5 = __toESM(require("path"));
|
|
10460
|
+
var YAML2 = __toESM(require("yaml"));
|
|
7669
10461
|
function parseJobConfig(jobConfigPath) {
|
|
7670
|
-
const jobConfigContent =
|
|
7671
|
-
const ext =
|
|
10462
|
+
const jobConfigContent = fs6.readFileSync(jobConfigPath, "utf-8");
|
|
10463
|
+
const ext = import_path5.default.extname(jobConfigPath);
|
|
7672
10464
|
switch (ext) {
|
|
7673
10465
|
case ".json":
|
|
7674
10466
|
return JSON.parse(jobConfigContent);
|
|
7675
10467
|
case ".yaml":
|
|
7676
10468
|
case ".yml":
|
|
7677
|
-
return
|
|
10469
|
+
return YAML2.parse(jobConfigContent);
|
|
7678
10470
|
default:
|
|
7679
10471
|
throw new Error(`Unsupported file extension: ${ext}`);
|
|
7680
10472
|
}
|
|
7681
10473
|
}
|
|
7682
|
-
async function publish(notebookPath, jobConfigPath,
|
|
7683
|
-
if (!
|
|
10474
|
+
async function publish(notebookPath, jobConfigPath, jobClient, accessToken) {
|
|
10475
|
+
if (!fs6.existsSync(notebookPath)) {
|
|
7684
10476
|
console.error(`File not found: ${notebookPath}`);
|
|
7685
10477
|
throw new Error(`File not found: ${notebookPath}`);
|
|
7686
10478
|
}
|
|
7687
|
-
if (!
|
|
10479
|
+
if (!fs6.existsSync(jobConfigPath)) {
|
|
7688
10480
|
console.error(`File not found: ${jobConfigPath}`);
|
|
7689
10481
|
throw new Error(`File not found: ${jobConfigPath}`);
|
|
7690
10482
|
}
|
|
7691
|
-
const
|
|
10483
|
+
const requestId = import_common40.CorrelationService.createCorrelationContext();
|
|
10484
|
+
const notebookBase64 = fs6.readFileSync(notebookPath).toString("base64");
|
|
7692
10485
|
const jobConfig = parseJobConfig(jobConfigPath);
|
|
7693
|
-
const payload = (0,
|
|
10486
|
+
const payload = (0, import_common40.buildCompleteJobPayload)(jobConfig, notebookBase64);
|
|
7694
10487
|
const jobName = jobConfig.jobName;
|
|
7695
|
-
await
|
|
10488
|
+
await jobClient.createJob(jobName, payload, accessToken, requestId);
|
|
7696
10489
|
return jobName;
|
|
7697
10490
|
}
|
|
7698
10491
|
|
|
7699
|
-
// src/
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
|
|
10492
|
+
// src/commands/publishJob.ts
|
|
10493
|
+
function addPublishCommand(jobCommand) {
|
|
10494
|
+
jobCommand.command("publish <notebookPath>").description("Publish a scheduled job.").option("-c, --config <path>", "Path to job YAML config").option("-r, --region <region>", "Target region (e.g. eastus2)", import_common41.Region.Global).action(async (notebookPath, options) => {
|
|
10495
|
+
try {
|
|
10496
|
+
const resolvedNotebookPath = import_path6.default.resolve(notebookPath);
|
|
10497
|
+
const resolvedConfigPath = import_path6.default.resolve(options.config);
|
|
10498
|
+
const apiEnv4 = (0, import_common41.getApiEnv)(import_common41.SecurityPlatformEnvironment.Production);
|
|
10499
|
+
const region = options.region;
|
|
10500
|
+
const accessToken = await getToken(apiEnv4);
|
|
10501
|
+
const jobApiClient = createJobApiClient(apiEnv4, region);
|
|
10502
|
+
const result = await publish(resolvedNotebookPath, resolvedConfigPath, jobApiClient, accessToken);
|
|
10503
|
+
console.log("Published job:", result);
|
|
10504
|
+
} catch (error) {
|
|
10505
|
+
handleApiError("publishing job", error);
|
|
10506
|
+
}
|
|
10507
|
+
});
|
|
10508
|
+
}
|
|
7706
10509
|
|
|
7707
|
-
// src/
|
|
10510
|
+
// src/commands/tenant/tenantList.ts
|
|
7708
10511
|
init_cjs_shims();
|
|
10512
|
+
var import_common43 = __toESM(require_src());
|
|
7709
10513
|
|
|
7710
|
-
// src/
|
|
10514
|
+
// src/services/tenant/index.ts
|
|
7711
10515
|
init_cjs_shims();
|
|
7712
10516
|
|
|
7713
|
-
// src/
|
|
10517
|
+
// src/services/tenant/tenantService.ts
|
|
7714
10518
|
init_cjs_shims();
|
|
7715
|
-
var
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
throw new Error("Environment cannot be null or undefined");
|
|
7721
|
-
}
|
|
7722
|
-
this.env = env;
|
|
7723
|
-
this.options = {
|
|
7724
|
-
...options,
|
|
7725
|
-
// overrides defaults if user provided values
|
|
7726
|
-
scopes: options?.scopes ?? [this.env.gatewayAuthResourceUri]
|
|
7727
|
-
};
|
|
10519
|
+
var import_common42 = __toESM(require_src());
|
|
10520
|
+
var TenantService = class {
|
|
10521
|
+
constructor(requestService, armEndpoint) {
|
|
10522
|
+
this.requestService = requestService;
|
|
10523
|
+
this.armEndpoint = armEndpoint;
|
|
7728
10524
|
}
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
|
|
7734
|
-
|
|
7735
|
-
|
|
10525
|
+
/**
|
|
10526
|
+
* Fetches all tenants accessible to the authenticated user from ARM.
|
|
10527
|
+
*
|
|
10528
|
+
* @param accessToken - A valid ARM bearer access token.
|
|
10529
|
+
* @returns An array of {@link ArmTenant} objects.
|
|
10530
|
+
*/
|
|
10531
|
+
async fetchAllTenants(accessToken) {
|
|
10532
|
+
const client = new import_common42.TenantApiClient({ requestService: this.requestService, armEndpoint: this.armEndpoint });
|
|
10533
|
+
return client.fetchAllTenants(accessToken);
|
|
7736
10534
|
}
|
|
7737
10535
|
};
|
|
7738
10536
|
|
|
7739
|
-
// src/
|
|
7740
|
-
|
|
7741
|
-
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
|
|
7747
|
-
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
|
|
7752
|
-
|
|
7753
|
-
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
scopes: options?.scopes ?? [env.gatewayAuthResourceUri]
|
|
7757
|
-
};
|
|
7758
|
-
}
|
|
7759
|
-
async getAccessToken() {
|
|
7760
|
-
const scopes = this.options?.scopes && this.options.scopes.length > 0 ? this.options.scopes : [this.env.gatewayAuthResourceUri];
|
|
7761
|
-
const credential = new import_identity3.ManagedIdentityCredential({
|
|
7762
|
-
clientId: this.options?.uamiClientId
|
|
7763
|
-
});
|
|
7764
|
-
const token = await credential.getToken(scopes);
|
|
7765
|
-
if (!token) {
|
|
7766
|
-
throw new Error("Failed to get token from Managed Identity");
|
|
10537
|
+
// src/commands/tenant/tenantList.ts
|
|
10538
|
+
var TENANT_COLUMNS = [
|
|
10539
|
+
{ header: "DISPLAY NAME", key: (t) => t.displayName },
|
|
10540
|
+
{ header: "TENANT ID", key: (t) => t.tenantId },
|
|
10541
|
+
{ header: "DEFAULT DOMAIN", key: (t) => t.defaultDomain }
|
|
10542
|
+
];
|
|
10543
|
+
function addTenantListCommand(tenantCommand) {
|
|
10544
|
+
tenantCommand.command("list").description("List accessible tenants for the signed-in user").action(async () => {
|
|
10545
|
+
try {
|
|
10546
|
+
const apiEnv4 = (0, import_common43.getApiEnv)(import_common43.SecurityPlatformEnvironment.Production);
|
|
10547
|
+
const accessToken = await getToken(apiEnv4, [apiEnv4.armScope]);
|
|
10548
|
+
const requestService = new import_common43.RequestService(noopTelemetry, buildApiHeaders);
|
|
10549
|
+
const tenantService = new TenantService(requestService, apiEnv4.armEndpoint);
|
|
10550
|
+
const tenants = await tenantService.fetchAllTenants(accessToken);
|
|
10551
|
+
printTenants(tenants);
|
|
10552
|
+
} catch (error) {
|
|
10553
|
+
handleApiError("listing tenants", error);
|
|
7767
10554
|
}
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
|
|
10555
|
+
});
|
|
10556
|
+
}
|
|
10557
|
+
function printTenants(tenants) {
|
|
10558
|
+
const fmt = new OutputFormatter();
|
|
10559
|
+
fmt.print(tenants, TENANT_COLUMNS);
|
|
10560
|
+
}
|
|
7771
10561
|
|
|
7772
|
-
// src/
|
|
10562
|
+
// src/commands/tenant/tenantSelect.ts
|
|
7773
10563
|
init_cjs_shims();
|
|
7774
|
-
var
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
10564
|
+
var import_common44 = __toESM(require_src());
|
|
10565
|
+
var os6 = __toESM(require("os"));
|
|
10566
|
+
var readline = __toESM(require("readline"));
|
|
10567
|
+
var MAX_PROMPT_ATTEMPTS = 3;
|
|
10568
|
+
function addTenantSelectCommand(tenantCommand) {
|
|
10569
|
+
tenantCommand.command("select").description(
|
|
10570
|
+
"Select an active tenant for this account from an interactive numbered prompt. Subsequent commands will acquire tokens for the selected tenant."
|
|
10571
|
+
).action(async () => {
|
|
10572
|
+
try {
|
|
10573
|
+
const apiEnv4 = (0, import_common44.getApiEnv)(import_common44.SecurityPlatformEnvironment.Production);
|
|
10574
|
+
const armToken = await getToken(apiEnv4, [apiEnv4.armScope]);
|
|
10575
|
+
const requestService = new import_common44.RequestService(noopTelemetry, buildApiHeaders);
|
|
10576
|
+
const tenantService = new TenantService(requestService, apiEnv4.armEndpoint);
|
|
10577
|
+
const tenants = await tenantService.fetchAllTenants(armToken);
|
|
10578
|
+
if (tenants.length === 0) {
|
|
10579
|
+
console.error("\u274C No tenants accessible for the signed-in account.");
|
|
10580
|
+
process.exit(1);
|
|
10581
|
+
}
|
|
10582
|
+
const activeTenantId = getActiveTenantId();
|
|
10583
|
+
const activeIndex = activeTenantId ? tenants.findIndex((t) => t.tenantId === activeTenantId) : -1;
|
|
10584
|
+
const chosen = await promptForTenant(tenants, activeIndex);
|
|
10585
|
+
if (!chosen) {
|
|
10586
|
+
console.log("\u2139 Active tenant unchanged.");
|
|
10587
|
+
return;
|
|
10588
|
+
}
|
|
10589
|
+
await switchActiveTenant(apiEnv4, chosen);
|
|
10590
|
+
console.log(`\u2705 Active tenant set to ${chosen.tenantId} (${chosen.displayName}).`);
|
|
10591
|
+
} catch (error) {
|
|
10592
|
+
handleApiError("selecting tenant", error);
|
|
7780
10593
|
}
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
|
|
10594
|
+
});
|
|
10595
|
+
}
|
|
10596
|
+
function getActiveTenantId() {
|
|
10597
|
+
const session = loadBrokerAccount();
|
|
10598
|
+
if (!session) {
|
|
10599
|
+
return null;
|
|
7786
10600
|
}
|
|
7787
|
-
|
|
7788
|
-
const
|
|
7789
|
-
|
|
7790
|
-
|
|
10601
|
+
try {
|
|
10602
|
+
const url = new URL(session.authority);
|
|
10603
|
+
const segment = url.pathname.split("/").filter(Boolean).pop();
|
|
10604
|
+
if (!segment || segment === "common" || segment === "organizations" || segment === "consumers") {
|
|
10605
|
+
return null;
|
|
7791
10606
|
}
|
|
7792
|
-
return
|
|
10607
|
+
return segment;
|
|
10608
|
+
} catch {
|
|
10609
|
+
return null;
|
|
7793
10610
|
}
|
|
7794
|
-
}
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
|
|
7799
|
-
|
|
7800
|
-
|
|
7801
|
-
|
|
7802
|
-
|
|
7803
|
-
|
|
7804
|
-
|
|
10611
|
+
}
|
|
10612
|
+
async function promptForTenant(tenants, activeIndex) {
|
|
10613
|
+
const defaultIdx = activeIndex >= 0 ? activeIndex + 1 : 1;
|
|
10614
|
+
console.log("");
|
|
10615
|
+
console.log(formatTenantTable(tenants, activeIndex));
|
|
10616
|
+
console.log("");
|
|
10617
|
+
if (activeIndex >= 0) {
|
|
10618
|
+
console.log(`The default is marked with an *; the default tenant is '${tenants[activeIndex].tenantId}'.`);
|
|
10619
|
+
console.log("");
|
|
10620
|
+
}
|
|
10621
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
10622
|
+
try {
|
|
10623
|
+
for (let attempt = 0; attempt < MAX_PROMPT_ATTEMPTS; attempt++) {
|
|
10624
|
+
const answer = await new Promise((resolve2) => {
|
|
10625
|
+
rl.question(`Select a tenant by number [${defaultIdx}]: `, (a) => resolve2(a));
|
|
10626
|
+
});
|
|
10627
|
+
const trimmed = answer.trim();
|
|
10628
|
+
if (trimmed === "") {
|
|
10629
|
+
if (activeIndex >= 0) {
|
|
10630
|
+
return null;
|
|
7805
10631
|
}
|
|
7806
|
-
return
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
|
|
7810
|
-
|
|
10632
|
+
return tenants[defaultIdx - 1];
|
|
10633
|
+
}
|
|
10634
|
+
if (/^\d+$/.test(trimmed)) {
|
|
10635
|
+
const idx = Number.parseInt(trimmed, 10);
|
|
10636
|
+
if (idx >= 1 && idx <= tenants.length) {
|
|
10637
|
+
const chosen = tenants[idx - 1];
|
|
10638
|
+
if (activeIndex >= 0 && idx - 1 === activeIndex) {
|
|
10639
|
+
return null;
|
|
10640
|
+
}
|
|
10641
|
+
return chosen;
|
|
10642
|
+
}
|
|
10643
|
+
}
|
|
10644
|
+
console.error(`Invalid selection. Enter a number between 1 and ${tenants.length}.`);
|
|
7811
10645
|
}
|
|
10646
|
+
throw new Error("Too many invalid attempts. Aborting.");
|
|
10647
|
+
} finally {
|
|
10648
|
+
rl.close();
|
|
7812
10649
|
}
|
|
7813
|
-
};
|
|
7814
|
-
|
|
7815
|
-
// src/services/getToken.ts
|
|
7816
|
-
async function getToken(env, scopes, clientId) {
|
|
7817
|
-
let provider = null;
|
|
7818
|
-
const options = {
|
|
7819
|
-
uamiClientId: clientId,
|
|
7820
|
-
scopes
|
|
7821
|
-
};
|
|
7822
|
-
if (clientId) {
|
|
7823
|
-
provider = TokenProviderFactory.createProvider(env, "managed_identity" /* ManagedIdentity */, options);
|
|
7824
|
-
} else {
|
|
7825
|
-
provider = TokenProviderFactory.createProvider(env, "msal_cache" /* MsalCache */, options);
|
|
7826
|
-
}
|
|
7827
|
-
const token = await provider.getAccessToken();
|
|
7828
|
-
return token;
|
|
7829
10650
|
}
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
10651
|
+
function formatTenantTable(tenants, activeIndex) {
|
|
10652
|
+
const headers = ["No.", "", "Tenant ID", "Tenant Name", "Default Domain"];
|
|
10653
|
+
const rows = tenants.map((t, i) => {
|
|
10654
|
+
const marker = i === activeIndex ? "*" : "";
|
|
10655
|
+
return [`[${i + 1}]`, marker, t.tenantId, t.displayName, t.defaultDomain ?? ""];
|
|
10656
|
+
});
|
|
10657
|
+
const widths = headers.map((h, col) => Math.max(h.length, ...rows.map((r) => r[col].length)));
|
|
10658
|
+
const pad = (s, w) => s + " ".repeat(Math.max(0, w - s.length));
|
|
10659
|
+
const formatRow = (cells) => cells.map((c, i) => pad(c, widths[i])).join(" ");
|
|
10660
|
+
return [formatRow(headers), ...rows.map(formatRow)].join("\n");
|
|
10661
|
+
}
|
|
10662
|
+
async function switchActiveTenant(apiEnv4, chosen) {
|
|
10663
|
+
const newAuthority = `${new URL(apiEnv4.aadEndpoint).origin}/${chosen.tenantId}`;
|
|
10664
|
+
const session = loadBrokerAccount();
|
|
10665
|
+
if (!session) {
|
|
10666
|
+
throw new Error(
|
|
10667
|
+
"No active session found. Run 'sentinel login' first. Note: tenant switching is not supported for managed-identity / workload-identity sign-ins."
|
|
7842
10668
|
);
|
|
7843
|
-
} catch {
|
|
7844
|
-
throw new Error("Failed to retrieve access token");
|
|
7845
10669
|
}
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
const jobService = new import_common8.JobService(apiEnv4, region, httpService);
|
|
7858
|
-
const result = await publish(resolvedNotebookPath, resolvedConfigPath, jobService);
|
|
7859
|
-
console.log("Published job:", result);
|
|
7860
|
-
} catch (error) {
|
|
7861
|
-
if (error instanceof Error) {
|
|
7862
|
-
console.error("Publish Error:", error.message);
|
|
7863
|
-
} else {
|
|
7864
|
-
console.error("Unknown error in publish:", error);
|
|
7865
|
-
}
|
|
7866
|
-
process.exit(1);
|
|
10670
|
+
const msalInstance = await getMsalInstance(apiEnv4, newAuthority);
|
|
10671
|
+
try {
|
|
10672
|
+
const result = await msalInstance.acquireTokenSilent({
|
|
10673
|
+
account: session.account,
|
|
10674
|
+
scopes: [apiEnv4.gatewayAuthResourceUri],
|
|
10675
|
+
authority: newAuthority
|
|
10676
|
+
});
|
|
10677
|
+
const acquiredTid = result?.account?.tenantId;
|
|
10678
|
+
if (result?.accessToken && acquiredTid === chosen.tenantId) {
|
|
10679
|
+
saveBrokerAccount(result.account, newAuthority);
|
|
10680
|
+
return;
|
|
7867
10681
|
}
|
|
7868
|
-
}
|
|
10682
|
+
} catch {
|
|
10683
|
+
}
|
|
10684
|
+
console.log(`\u2139 Silent sign-in to tenant ${chosen.tenantId} not possible \u2014 prompting interactively\u2026`);
|
|
10685
|
+
if (os6.platform() === "win32") {
|
|
10686
|
+
await brokerLogin([apiEnv4.gatewayAuthResourceUri], chosen.tenantId);
|
|
10687
|
+
} else {
|
|
10688
|
+
await browserAuthLogin([apiEnv4.gatewayAuthResourceUri], chosen.tenantId);
|
|
10689
|
+
}
|
|
7869
10690
|
}
|
|
7870
10691
|
|
|
7871
10692
|
// src/commands/token.ts
|
|
@@ -7876,17 +10697,79 @@ function addTokenCommand(program2) {
|
|
|
7876
10697
|
});
|
|
7877
10698
|
}
|
|
7878
10699
|
|
|
10700
|
+
// src/commands/updateCLI.ts
|
|
10701
|
+
init_cjs_shims();
|
|
10702
|
+
|
|
10703
|
+
// src/actions/updateCLI.ts
|
|
10704
|
+
init_cjs_shims();
|
|
10705
|
+
var import_axios = __toESM(require("axios"));
|
|
10706
|
+
var import_child_process2 = require("child_process");
|
|
10707
|
+
var os7 = __toESM(require("os"));
|
|
10708
|
+
var import_semver = __toESM(require("semver"));
|
|
10709
|
+
var PACKAGE_NAME = "@microsoft/sentinel-cli";
|
|
10710
|
+
var NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
10711
|
+
async function fetchLatestVersion() {
|
|
10712
|
+
const response = await import_axios.default.get(NPM_REGISTRY_URL, { timeout: 5e3 });
|
|
10713
|
+
return response.data.version;
|
|
10714
|
+
}
|
|
10715
|
+
function isNewerVersion(current, latest) {
|
|
10716
|
+
const c = import_semver.default.coerce(current);
|
|
10717
|
+
const l = import_semver.default.coerce(latest);
|
|
10718
|
+
if (!c || !l) {
|
|
10719
|
+
return false;
|
|
10720
|
+
}
|
|
10721
|
+
return import_semver.default.gt(l, c);
|
|
10722
|
+
}
|
|
10723
|
+
function runUpdateCommand(version) {
|
|
10724
|
+
if (!import_semver.default.valid(version)) {
|
|
10725
|
+
throw new Error(`Invalid version: ${version}`);
|
|
10726
|
+
}
|
|
10727
|
+
const args = ["install", "-g", `${PACKAGE_NAME}@${version}`];
|
|
10728
|
+
(0, import_child_process2.execFileSync)("npm", args, { stdio: "inherit", shell: true });
|
|
10729
|
+
}
|
|
10730
|
+
async function checkAndUpdate(currentVersion) {
|
|
10731
|
+
console.log(`\u{1F50D} Current version: ${currentVersion}`);
|
|
10732
|
+
console.log("\u{1F310} Checking for latest version on npm...");
|
|
10733
|
+
const latestVersion = await fetchLatestVersion();
|
|
10734
|
+
if (!isNewerVersion(currentVersion, latestVersion)) {
|
|
10735
|
+
console.log(`\u2705 You are already on the latest version (${currentVersion}).`);
|
|
10736
|
+
return;
|
|
10737
|
+
}
|
|
10738
|
+
console.log(`\u{1F4E6} New version available: ${latestVersion}`);
|
|
10739
|
+
console.log(`\u2B06\uFE0F Updating from ${currentVersion} to ${latestVersion}...`);
|
|
10740
|
+
if (os7.platform() !== "win32") {
|
|
10741
|
+
console.log(
|
|
10742
|
+
"\u2139\uFE0F On macOS/Linux, you may need administrator privileges. If the update fails, try running with sudo."
|
|
10743
|
+
);
|
|
10744
|
+
}
|
|
10745
|
+
runUpdateCommand(latestVersion);
|
|
10746
|
+
console.log(`\u2705 Successfully updated to version ${latestVersion}.`);
|
|
10747
|
+
}
|
|
10748
|
+
|
|
10749
|
+
// src/commands/updateCLI.ts
|
|
10750
|
+
function addUpdateCliCommand(program2) {
|
|
10751
|
+
program2.command("update").description("Update the Sentinel CLI to the latest version").action(async () => {
|
|
10752
|
+
try {
|
|
10753
|
+
await checkAndUpdate("0.3.0");
|
|
10754
|
+
} catch (error) {
|
|
10755
|
+
console.error(`\u274C Update failed: ${error instanceof Error ? error.message : error}`);
|
|
10756
|
+
process.exitCode = 1;
|
|
10757
|
+
return;
|
|
10758
|
+
}
|
|
10759
|
+
});
|
|
10760
|
+
}
|
|
10761
|
+
|
|
7879
10762
|
// src/commands/validate.ts
|
|
7880
10763
|
init_cjs_shims();
|
|
7881
10764
|
|
|
7882
10765
|
// src/actions/validate.ts
|
|
7883
10766
|
init_cjs_shims();
|
|
7884
|
-
var
|
|
10767
|
+
var import_common45 = __toESM(require_src());
|
|
7885
10768
|
async function validateFromFile(filePath) {
|
|
7886
10769
|
if (!filePath || typeof filePath !== "string" || filePath.trim().length === 0) {
|
|
7887
10770
|
throw new Error("Invalid file path provided.");
|
|
7888
10771
|
}
|
|
7889
|
-
const manifestProcessorService = new
|
|
10772
|
+
const manifestProcessorService = new import_common45.ManifestProcessorService();
|
|
7890
10773
|
console.info("Starting validate process...");
|
|
7891
10774
|
await manifestProcessorService.validateManifest(filePath);
|
|
7892
10775
|
}
|
|
@@ -7913,15 +10796,56 @@ function addValidateCommand(packageCommand) {
|
|
|
7913
10796
|
function registerCommands(program2) {
|
|
7914
10797
|
const jobCommand = program2.command("job").description("Manage scheduled jobs");
|
|
7915
10798
|
addPublishCommand(jobCommand);
|
|
10799
|
+
addJobListCommand(jobCommand);
|
|
10800
|
+
addJobShowCommand(jobCommand);
|
|
10801
|
+
addJobDeleteCommand(jobCommand);
|
|
10802
|
+
addJobDisableCommand(jobCommand);
|
|
10803
|
+
addJobEnableCommand(jobCommand);
|
|
10804
|
+
addJobDownloadCommand(jobCommand);
|
|
10805
|
+
const runCommand = jobCommand.command("run").description("Manage job runs");
|
|
10806
|
+
addJobRunListCommand(runCommand);
|
|
10807
|
+
addJobRunShowCommand(runCommand);
|
|
10808
|
+
addJobRunStartCommand(runCommand);
|
|
10809
|
+
addJobRunCancelCommand(runCommand);
|
|
10810
|
+
const notebookCommand = runCommand.command("notebook").description("Manage job run notebooks");
|
|
10811
|
+
addJobRunNotebookDownloadCommand(notebookCommand);
|
|
10812
|
+
const definitionCommand = jobCommand.command("definition").description("Manage job definition YAML files");
|
|
10813
|
+
addJobDefinitionCreateCommand(definitionCommand);
|
|
10814
|
+
addJobDefinitionShowCommand(definitionCommand);
|
|
10815
|
+
addJobDefinitionUpdateCommand(definitionCommand);
|
|
7916
10816
|
const packageCommand = program2.command("package").description("Manage packages");
|
|
7917
10817
|
addCreateZipCommand(packageCommand);
|
|
7918
10818
|
addValidateCommand(packageCommand);
|
|
10819
|
+
const databaseCommand = program2.command("database").description("Manage sentinel lake databases");
|
|
10820
|
+
addDatabaseCommand(databaseCommand);
|
|
10821
|
+
const tableCommand = program2.command("table").description("Manage sentinel lake tables");
|
|
10822
|
+
addLakeTableListCommand(tableCommand);
|
|
10823
|
+
addLakeTableShowCommand(tableCommand);
|
|
10824
|
+
const tenantCommand = program2.command("tenant").description("Manage tenants");
|
|
10825
|
+
addTenantListCommand(tenantCommand);
|
|
10826
|
+
addTenantSelectCommand(tenantCommand);
|
|
7919
10827
|
loginCommand(program2);
|
|
7920
10828
|
logoutCommand(program2);
|
|
7921
10829
|
addTokenCommand(program2);
|
|
10830
|
+
addUpdateCliCommand(program2);
|
|
7922
10831
|
}
|
|
7923
10832
|
|
|
7924
10833
|
// src/index.ts
|
|
7925
|
-
import_commander.program.name("sentinel").description("CLI
|
|
10834
|
+
import_commander.program.name("sentinel").description("Sentinel CLI \u2014 manage lake tables, databases, scheduled jobs, packages, and authentication").version("0.3.0");
|
|
7926
10835
|
registerCommands(import_commander.program);
|
|
7927
|
-
|
|
10836
|
+
var telemetry = getTelemetry();
|
|
10837
|
+
telemetry.event("cli.invoked", {
|
|
10838
|
+
properties: { command: process.argv[2] ?? "<none>" }
|
|
10839
|
+
});
|
|
10840
|
+
attachCommandTelemetry(import_commander.program, telemetry);
|
|
10841
|
+
(async () => {
|
|
10842
|
+
let exitCode = 0;
|
|
10843
|
+
try {
|
|
10844
|
+
await import_commander.program.parseAsync(process.argv);
|
|
10845
|
+
} catch {
|
|
10846
|
+
exitCode = 1;
|
|
10847
|
+
} finally {
|
|
10848
|
+
await telemetry.dispose();
|
|
10849
|
+
}
|
|
10850
|
+
process.exit(exitCode);
|
|
10851
|
+
})();
|