timeback 0.1.9 → 0.1.10
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/cli.js +275 -35
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -17383,6 +17383,8 @@ var ActivityCompletedInput = exports_external.object({
|
|
|
17383
17383
|
metricsId: exports_external.string().optional(),
|
|
17384
17384
|
id: exports_external.string().optional(),
|
|
17385
17385
|
extensions: exports_external.record(exports_external.string(), exports_external.unknown()).optional(),
|
|
17386
|
+
edApp: exports_external.union([exports_external.string(), exports_external.record(exports_external.string(), exports_external.unknown())]).optional(),
|
|
17387
|
+
session: exports_external.union([exports_external.string(), exports_external.record(exports_external.string(), exports_external.unknown())]).optional(),
|
|
17386
17388
|
attempt: exports_external.number().int().min(1).optional(),
|
|
17387
17389
|
generatedExtensions: exports_external.object({
|
|
17388
17390
|
pctCompleteApp: exports_external.number().optional()
|
|
@@ -17395,7 +17397,9 @@ var TimeSpentInput = exports_external.object({
|
|
|
17395
17397
|
eventTime: IsoDateTimeString.optional(),
|
|
17396
17398
|
metricsId: exports_external.string().optional(),
|
|
17397
17399
|
id: exports_external.string().optional(),
|
|
17398
|
-
extensions: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
17400
|
+
extensions: exports_external.record(exports_external.string(), exports_external.unknown()).optional(),
|
|
17401
|
+
edApp: exports_external.union([exports_external.string(), exports_external.record(exports_external.string(), exports_external.unknown())]).optional(),
|
|
17402
|
+
session: exports_external.union([exports_external.string(), exports_external.record(exports_external.string(), exports_external.unknown())]).optional()
|
|
17399
17403
|
}).strict();
|
|
17400
17404
|
var TimebackEvent = exports_external.union([TimebackActivityEvent, TimebackTimeSpentEvent]);
|
|
17401
17405
|
var CaliperEnvelope = exports_external.object({
|
|
@@ -17583,7 +17587,7 @@ var TimebackConfig = exports_external.object({
|
|
|
17583
17587
|
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
17584
17588
|
path: ["courses"]
|
|
17585
17589
|
});
|
|
17586
|
-
var EdubridgeDateString = IsoDateTimeString;
|
|
17590
|
+
var EdubridgeDateString = exports_external.union([IsoDateTimeString, IsoDateString]);
|
|
17587
17591
|
var EduBridgeEnrollment = exports_external.object({
|
|
17588
17592
|
id: exports_external.string(),
|
|
17589
17593
|
role: exports_external.string(),
|
|
@@ -18578,7 +18582,9 @@ function createActivityEvent(input) {
|
|
|
18578
18582
|
...input.attempt === undefined ? {} : { attempt: input.attempt },
|
|
18579
18583
|
...input.generatedExtensions ? { extensions: input.generatedExtensions } : {}
|
|
18580
18584
|
},
|
|
18581
|
-
extensions: input.extensions
|
|
18585
|
+
extensions: input.extensions,
|
|
18586
|
+
...input.edApp === undefined ? {} : { edApp: input.edApp },
|
|
18587
|
+
...input.session === undefined ? {} : { session: input.session }
|
|
18582
18588
|
};
|
|
18583
18589
|
}
|
|
18584
18590
|
function createTimeSpentEvent(input) {
|
|
@@ -18598,7 +18604,9 @@ function createTimeSpentEvent(input) {
|
|
|
18598
18604
|
type: "TimebackTimeSpentMetricsCollection",
|
|
18599
18605
|
items: input.metrics
|
|
18600
18606
|
},
|
|
18601
|
-
extensions: input.extensions
|
|
18607
|
+
extensions: input.extensions,
|
|
18608
|
+
...input.edApp === undefined ? {} : { edApp: input.edApp },
|
|
18609
|
+
...input.session === undefined ? {} : { session: input.session }
|
|
18602
18610
|
};
|
|
18603
18611
|
}
|
|
18604
18612
|
|
|
@@ -33811,6 +33819,8 @@ var ActivityCompletedInput2 = exports_external2.object({
|
|
|
33811
33819
|
metricsId: exports_external2.string().optional(),
|
|
33812
33820
|
id: exports_external2.string().optional(),
|
|
33813
33821
|
extensions: exports_external2.record(exports_external2.string(), exports_external2.unknown()).optional(),
|
|
33822
|
+
edApp: exports_external2.union([exports_external2.string(), exports_external2.record(exports_external2.string(), exports_external2.unknown())]).optional(),
|
|
33823
|
+
session: exports_external2.union([exports_external2.string(), exports_external2.record(exports_external2.string(), exports_external2.unknown())]).optional(),
|
|
33814
33824
|
attempt: exports_external2.number().int().min(1).optional(),
|
|
33815
33825
|
generatedExtensions: exports_external2.object({
|
|
33816
33826
|
pctCompleteApp: exports_external2.number().optional()
|
|
@@ -33823,7 +33833,9 @@ var TimeSpentInput2 = exports_external2.object({
|
|
|
33823
33833
|
eventTime: IsoDateTimeString2.optional(),
|
|
33824
33834
|
metricsId: exports_external2.string().optional(),
|
|
33825
33835
|
id: exports_external2.string().optional(),
|
|
33826
|
-
extensions: exports_external2.record(exports_external2.string(), exports_external2.unknown()).optional()
|
|
33836
|
+
extensions: exports_external2.record(exports_external2.string(), exports_external2.unknown()).optional(),
|
|
33837
|
+
edApp: exports_external2.union([exports_external2.string(), exports_external2.record(exports_external2.string(), exports_external2.unknown())]).optional(),
|
|
33838
|
+
session: exports_external2.union([exports_external2.string(), exports_external2.record(exports_external2.string(), exports_external2.unknown())]).optional()
|
|
33827
33839
|
}).strict();
|
|
33828
33840
|
var TimebackEvent2 = exports_external2.union([TimebackActivityEvent2, TimebackTimeSpentEvent2]);
|
|
33829
33841
|
var CaliperEnvelope2 = exports_external2.object({
|
|
@@ -34011,7 +34023,7 @@ var TimebackConfig2 = exports_external2.object({
|
|
|
34011
34023
|
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
34012
34024
|
path: ["courses"]
|
|
34013
34025
|
});
|
|
34014
|
-
var EdubridgeDateString2 = IsoDateTimeString2;
|
|
34026
|
+
var EdubridgeDateString2 = exports_external2.union([IsoDateTimeString2, IsoDateString2]);
|
|
34015
34027
|
var EduBridgeEnrollment2 = exports_external2.object({
|
|
34016
34028
|
id: exports_external2.string(),
|
|
34017
34029
|
role: exports_external2.string(),
|
|
@@ -51297,6 +51309,8 @@ var ActivityCompletedInput3 = exports_external3.object({
|
|
|
51297
51309
|
metricsId: exports_external3.string().optional(),
|
|
51298
51310
|
id: exports_external3.string().optional(),
|
|
51299
51311
|
extensions: exports_external3.record(exports_external3.string(), exports_external3.unknown()).optional(),
|
|
51312
|
+
edApp: exports_external3.union([exports_external3.string(), exports_external3.record(exports_external3.string(), exports_external3.unknown())]).optional(),
|
|
51313
|
+
session: exports_external3.union([exports_external3.string(), exports_external3.record(exports_external3.string(), exports_external3.unknown())]).optional(),
|
|
51300
51314
|
attempt: exports_external3.number().int().min(1).optional(),
|
|
51301
51315
|
generatedExtensions: exports_external3.object({
|
|
51302
51316
|
pctCompleteApp: exports_external3.number().optional()
|
|
@@ -51309,7 +51323,9 @@ var TimeSpentInput3 = exports_external3.object({
|
|
|
51309
51323
|
eventTime: IsoDateTimeString3.optional(),
|
|
51310
51324
|
metricsId: exports_external3.string().optional(),
|
|
51311
51325
|
id: exports_external3.string().optional(),
|
|
51312
|
-
extensions: exports_external3.record(exports_external3.string(), exports_external3.unknown()).optional()
|
|
51326
|
+
extensions: exports_external3.record(exports_external3.string(), exports_external3.unknown()).optional(),
|
|
51327
|
+
edApp: exports_external3.union([exports_external3.string(), exports_external3.record(exports_external3.string(), exports_external3.unknown())]).optional(),
|
|
51328
|
+
session: exports_external3.union([exports_external3.string(), exports_external3.record(exports_external3.string(), exports_external3.unknown())]).optional()
|
|
51313
51329
|
}).strict();
|
|
51314
51330
|
var TimebackEvent3 = exports_external3.union([TimebackActivityEvent3, TimebackTimeSpentEvent3]);
|
|
51315
51331
|
var CaliperEnvelope3 = exports_external3.object({
|
|
@@ -51497,7 +51513,7 @@ var TimebackConfig3 = exports_external3.object({
|
|
|
51497
51513
|
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
51498
51514
|
path: ["courses"]
|
|
51499
51515
|
});
|
|
51500
|
-
var EdubridgeDateString3 = IsoDateTimeString3;
|
|
51516
|
+
var EdubridgeDateString3 = exports_external3.union([IsoDateTimeString3, IsoDateString3]);
|
|
51501
51517
|
var EduBridgeEnrollment3 = exports_external3.object({
|
|
51502
51518
|
id: exports_external3.string(),
|
|
51503
51519
|
role: exports_external3.string(),
|
|
@@ -68960,6 +68976,8 @@ var ActivityCompletedInput4 = exports_external4.object({
|
|
|
68960
68976
|
metricsId: exports_external4.string().optional(),
|
|
68961
68977
|
id: exports_external4.string().optional(),
|
|
68962
68978
|
extensions: exports_external4.record(exports_external4.string(), exports_external4.unknown()).optional(),
|
|
68979
|
+
edApp: exports_external4.union([exports_external4.string(), exports_external4.record(exports_external4.string(), exports_external4.unknown())]).optional(),
|
|
68980
|
+
session: exports_external4.union([exports_external4.string(), exports_external4.record(exports_external4.string(), exports_external4.unknown())]).optional(),
|
|
68963
68981
|
attempt: exports_external4.number().int().min(1).optional(),
|
|
68964
68982
|
generatedExtensions: exports_external4.object({
|
|
68965
68983
|
pctCompleteApp: exports_external4.number().optional()
|
|
@@ -68972,7 +68990,9 @@ var TimeSpentInput4 = exports_external4.object({
|
|
|
68972
68990
|
eventTime: IsoDateTimeString4.optional(),
|
|
68973
68991
|
metricsId: exports_external4.string().optional(),
|
|
68974
68992
|
id: exports_external4.string().optional(),
|
|
68975
|
-
extensions: exports_external4.record(exports_external4.string(), exports_external4.unknown()).optional()
|
|
68993
|
+
extensions: exports_external4.record(exports_external4.string(), exports_external4.unknown()).optional(),
|
|
68994
|
+
edApp: exports_external4.union([exports_external4.string(), exports_external4.record(exports_external4.string(), exports_external4.unknown())]).optional(),
|
|
68995
|
+
session: exports_external4.union([exports_external4.string(), exports_external4.record(exports_external4.string(), exports_external4.unknown())]).optional()
|
|
68976
68996
|
}).strict();
|
|
68977
68997
|
var TimebackEvent4 = exports_external4.union([TimebackActivityEvent4, TimebackTimeSpentEvent4]);
|
|
68978
68998
|
var CaliperEnvelope4 = exports_external4.object({
|
|
@@ -69160,7 +69180,7 @@ var TimebackConfig4 = exports_external4.object({
|
|
|
69160
69180
|
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
69161
69181
|
path: ["courses"]
|
|
69162
69182
|
});
|
|
69163
|
-
var EdubridgeDateString4 = IsoDateTimeString4;
|
|
69183
|
+
var EdubridgeDateString4 = exports_external4.union([IsoDateTimeString4, IsoDateString4]);
|
|
69164
69184
|
var EduBridgeEnrollment4 = exports_external4.object({
|
|
69165
69185
|
id: exports_external4.string(),
|
|
69166
69186
|
role: exports_external4.string(),
|
|
@@ -85647,6 +85667,8 @@ var ActivityCompletedInput5 = exports_external5.object({
|
|
|
85647
85667
|
metricsId: exports_external5.string().optional(),
|
|
85648
85668
|
id: exports_external5.string().optional(),
|
|
85649
85669
|
extensions: exports_external5.record(exports_external5.string(), exports_external5.unknown()).optional(),
|
|
85670
|
+
edApp: exports_external5.union([exports_external5.string(), exports_external5.record(exports_external5.string(), exports_external5.unknown())]).optional(),
|
|
85671
|
+
session: exports_external5.union([exports_external5.string(), exports_external5.record(exports_external5.string(), exports_external5.unknown())]).optional(),
|
|
85650
85672
|
attempt: exports_external5.number().int().min(1).optional(),
|
|
85651
85673
|
generatedExtensions: exports_external5.object({
|
|
85652
85674
|
pctCompleteApp: exports_external5.number().optional()
|
|
@@ -85659,7 +85681,9 @@ var TimeSpentInput5 = exports_external5.object({
|
|
|
85659
85681
|
eventTime: IsoDateTimeString5.optional(),
|
|
85660
85682
|
metricsId: exports_external5.string().optional(),
|
|
85661
85683
|
id: exports_external5.string().optional(),
|
|
85662
|
-
extensions: exports_external5.record(exports_external5.string(), exports_external5.unknown()).optional()
|
|
85684
|
+
extensions: exports_external5.record(exports_external5.string(), exports_external5.unknown()).optional(),
|
|
85685
|
+
edApp: exports_external5.union([exports_external5.string(), exports_external5.record(exports_external5.string(), exports_external5.unknown())]).optional(),
|
|
85686
|
+
session: exports_external5.union([exports_external5.string(), exports_external5.record(exports_external5.string(), exports_external5.unknown())]).optional()
|
|
85663
85687
|
}).strict();
|
|
85664
85688
|
var TimebackEvent5 = exports_external5.union([TimebackActivityEvent5, TimebackTimeSpentEvent5]);
|
|
85665
85689
|
var CaliperEnvelope5 = exports_external5.object({
|
|
@@ -85847,7 +85871,7 @@ var TimebackConfig5 = exports_external5.object({
|
|
|
85847
85871
|
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
85848
85872
|
path: ["courses"]
|
|
85849
85873
|
});
|
|
85850
|
-
var EdubridgeDateString5 = IsoDateTimeString5;
|
|
85874
|
+
var EdubridgeDateString5 = exports_external5.union([IsoDateTimeString5, IsoDateString5]);
|
|
85851
85875
|
var EduBridgeEnrollment5 = exports_external5.object({
|
|
85852
85876
|
id: exports_external5.string(),
|
|
85853
85877
|
role: exports_external5.string(),
|
|
@@ -102072,13 +102096,14 @@ async function validateEmailWithTimeback(environment, clientId, clientSecret, em
|
|
|
102072
102096
|
if (page.data.length === 0) {
|
|
102073
102097
|
return {
|
|
102074
102098
|
valid: false,
|
|
102099
|
+
reason: "not_found",
|
|
102075
102100
|
error: `No user found with email "${email9}" in ${environment}`
|
|
102076
102101
|
};
|
|
102077
102102
|
}
|
|
102078
102103
|
return { valid: true };
|
|
102079
102104
|
} catch (error58) {
|
|
102080
102105
|
const message = error58 instanceof Error ? error58.message : "Unknown error";
|
|
102081
|
-
return { valid: false, error: `Failed to validate email: ${message}` };
|
|
102106
|
+
return { valid: false, reason: "api_error", error: `Failed to validate email: ${message}` };
|
|
102082
102107
|
}
|
|
102083
102108
|
}
|
|
102084
102109
|
|
|
@@ -102318,6 +102343,8 @@ var ActivityCompletedInput6 = exports_external6.object({
|
|
|
102318
102343
|
metricsId: exports_external6.string().optional(),
|
|
102319
102344
|
id: exports_external6.string().optional(),
|
|
102320
102345
|
extensions: exports_external6.record(exports_external6.string(), exports_external6.unknown()).optional(),
|
|
102346
|
+
edApp: exports_external6.union([exports_external6.string(), exports_external6.record(exports_external6.string(), exports_external6.unknown())]).optional(),
|
|
102347
|
+
session: exports_external6.union([exports_external6.string(), exports_external6.record(exports_external6.string(), exports_external6.unknown())]).optional(),
|
|
102321
102348
|
attempt: exports_external6.number().int().min(1).optional(),
|
|
102322
102349
|
generatedExtensions: exports_external6.object({
|
|
102323
102350
|
pctCompleteApp: exports_external6.number().optional()
|
|
@@ -102330,7 +102357,9 @@ var TimeSpentInput6 = exports_external6.object({
|
|
|
102330
102357
|
eventTime: IsoDateTimeString6.optional(),
|
|
102331
102358
|
metricsId: exports_external6.string().optional(),
|
|
102332
102359
|
id: exports_external6.string().optional(),
|
|
102333
|
-
extensions: exports_external6.record(exports_external6.string(), exports_external6.unknown()).optional()
|
|
102360
|
+
extensions: exports_external6.record(exports_external6.string(), exports_external6.unknown()).optional(),
|
|
102361
|
+
edApp: exports_external6.union([exports_external6.string(), exports_external6.record(exports_external6.string(), exports_external6.unknown())]).optional(),
|
|
102362
|
+
session: exports_external6.union([exports_external6.string(), exports_external6.record(exports_external6.string(), exports_external6.unknown())]).optional()
|
|
102334
102363
|
}).strict();
|
|
102335
102364
|
var TimebackEvent6 = exports_external6.union([TimebackActivityEvent6, TimebackTimeSpentEvent6]);
|
|
102336
102365
|
var CaliperEnvelope6 = exports_external6.object({
|
|
@@ -102520,7 +102549,7 @@ var TimebackConfig6 = exports_external6.object({
|
|
|
102520
102549
|
path: ["courses"]
|
|
102521
102550
|
});
|
|
102522
102551
|
// ../types/src/zod/edubridge.ts
|
|
102523
|
-
var EdubridgeDateString6 = IsoDateTimeString6;
|
|
102552
|
+
var EdubridgeDateString6 = exports_external6.union([IsoDateTimeString6, IsoDateString6]);
|
|
102524
102553
|
var EduBridgeEnrollment6 = exports_external6.object({
|
|
102525
102554
|
id: exports_external6.string(),
|
|
102526
102555
|
role: exports_external6.string(),
|
|
@@ -105596,7 +105625,7 @@ function logErrors(errors3) {
|
|
|
105596
105625
|
}
|
|
105597
105626
|
|
|
105598
105627
|
// src/version.ts
|
|
105599
|
-
var cliVersion = "0.1.
|
|
105628
|
+
var cliVersion = "0.1.10";
|
|
105600
105629
|
|
|
105601
105630
|
// src/lib/metadata.ts
|
|
105602
105631
|
function deepMerge(base, override) {
|
|
@@ -112336,6 +112365,7 @@ import { spawn as spawn2 } from "node:child_process";
|
|
|
112336
112365
|
import { existsSync as existsSync22 } from "node:fs";
|
|
112337
112366
|
import { resolve as resolve42 } from "node:path";
|
|
112338
112367
|
import { readFile as readFile32, writeFile as writeFile22 } from "node:fs/promises";
|
|
112368
|
+
import { randomUUID } from "node:crypto";
|
|
112339
112369
|
import { basename as basename22 } from "node:path";
|
|
112340
112370
|
import { createServer as createServerHTTP } from "http";
|
|
112341
112371
|
import { Http2ServerRequest as Http2ServerRequest2 } from "http2";
|
|
@@ -126965,13 +126995,14 @@ async function validateEmailWithTimeback2(environment, clientId, clientSecret, e
|
|
|
126965
126995
|
if (page.data.length === 0) {
|
|
126966
126996
|
return {
|
|
126967
126997
|
valid: false,
|
|
126998
|
+
reason: "not_found",
|
|
126968
126999
|
error: `No user found with email "${email32}" in ${environment}`
|
|
126969
127000
|
};
|
|
126970
127001
|
}
|
|
126971
127002
|
return { valid: true };
|
|
126972
127003
|
} catch (error482) {
|
|
126973
127004
|
const message = error482 instanceof Error ? error482.message : "Unknown error";
|
|
126974
|
-
return { valid: false, error: `Failed to validate email: ${message}` };
|
|
127005
|
+
return { valid: false, reason: "api_error", error: `Failed to validate email: ${message}` };
|
|
126975
127006
|
}
|
|
126976
127007
|
}
|
|
126977
127008
|
async function promptForCredentials2(environment) {
|
|
@@ -127264,6 +127295,8 @@ var ActivityCompletedInput8 = exports_external8.object({
|
|
|
127264
127295
|
metricsId: exports_external8.string().optional(),
|
|
127265
127296
|
id: exports_external8.string().optional(),
|
|
127266
127297
|
extensions: exports_external8.record(exports_external8.string(), exports_external8.unknown()).optional(),
|
|
127298
|
+
edApp: exports_external8.union([exports_external8.string(), exports_external8.record(exports_external8.string(), exports_external8.unknown())]).optional(),
|
|
127299
|
+
session: exports_external8.union([exports_external8.string(), exports_external8.record(exports_external8.string(), exports_external8.unknown())]).optional(),
|
|
127267
127300
|
attempt: exports_external8.number().int().min(1).optional(),
|
|
127268
127301
|
generatedExtensions: exports_external8.object({
|
|
127269
127302
|
pctCompleteApp: exports_external8.number().optional()
|
|
@@ -127276,7 +127309,9 @@ var TimeSpentInput8 = exports_external8.object({
|
|
|
127276
127309
|
eventTime: IsoDateTimeString8.optional(),
|
|
127277
127310
|
metricsId: exports_external8.string().optional(),
|
|
127278
127311
|
id: exports_external8.string().optional(),
|
|
127279
|
-
extensions: exports_external8.record(exports_external8.string(), exports_external8.unknown()).optional()
|
|
127312
|
+
extensions: exports_external8.record(exports_external8.string(), exports_external8.unknown()).optional(),
|
|
127313
|
+
edApp: exports_external8.union([exports_external8.string(), exports_external8.record(exports_external8.string(), exports_external8.unknown())]).optional(),
|
|
127314
|
+
session: exports_external8.union([exports_external8.string(), exports_external8.record(exports_external8.string(), exports_external8.unknown())]).optional()
|
|
127280
127315
|
}).strict();
|
|
127281
127316
|
var TimebackEvent8 = exports_external8.union([TimebackActivityEvent8, TimebackTimeSpentEvent8]);
|
|
127282
127317
|
var CaliperEnvelope8 = exports_external8.object({
|
|
@@ -127464,7 +127499,7 @@ var TimebackConfig8 = exports_external8.object({
|
|
|
127464
127499
|
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
127465
127500
|
path: ["courses"]
|
|
127466
127501
|
});
|
|
127467
|
-
var EdubridgeDateString8 = IsoDateTimeString8;
|
|
127502
|
+
var EdubridgeDateString8 = exports_external8.union([IsoDateTimeString8, IsoDateString8]);
|
|
127468
127503
|
var EduBridgeEnrollment8 = exports_external8.object({
|
|
127469
127504
|
id: exports_external8.string(),
|
|
127470
127505
|
role: exports_external8.string(),
|
|
@@ -129700,6 +129735,180 @@ async function addCredentials2(options = {}) {
|
|
|
129700
129735
|
if (exitOnComplete)
|
|
129701
129736
|
process.exit(0);
|
|
129702
129737
|
}
|
|
129738
|
+
async function promptName(label) {
|
|
129739
|
+
const value = await he2({
|
|
129740
|
+
message: label,
|
|
129741
|
+
placeholder: "Enter name",
|
|
129742
|
+
validate: (v2) => {
|
|
129743
|
+
if (!v2?.trim())
|
|
129744
|
+
return `${label} is required`;
|
|
129745
|
+
}
|
|
129746
|
+
});
|
|
129747
|
+
if (isCancelled2(value))
|
|
129748
|
+
return null;
|
|
129749
|
+
return value.trim();
|
|
129750
|
+
}
|
|
129751
|
+
async function searchOrganizations(client, query) {
|
|
129752
|
+
const allOrgs = await client.oneroster.orgs.listAll({
|
|
129753
|
+
where: { status: "active" },
|
|
129754
|
+
max: 100
|
|
129755
|
+
});
|
|
129756
|
+
if (!query.trim())
|
|
129757
|
+
return allOrgs;
|
|
129758
|
+
const lowerQuery = query.toLowerCase().trim();
|
|
129759
|
+
return allOrgs.filter((org) => org.name?.toLowerCase().includes(lowerQuery));
|
|
129760
|
+
}
|
|
129761
|
+
async function searchForOrganization(client) {
|
|
129762
|
+
const query = await he2({
|
|
129763
|
+
message: "Search for organization",
|
|
129764
|
+
placeholder: "Enter organization name to search"
|
|
129765
|
+
});
|
|
129766
|
+
if (isCancelled2(query))
|
|
129767
|
+
return null;
|
|
129768
|
+
const s = Y22();
|
|
129769
|
+
s.start("Searching organizations...");
|
|
129770
|
+
let results;
|
|
129771
|
+
try {
|
|
129772
|
+
results = await searchOrganizations(client, query);
|
|
129773
|
+
s.stop(green2(`Found ${results.length} result${results.length === 1 ? "" : "s"}`));
|
|
129774
|
+
} catch (error482) {
|
|
129775
|
+
s.stop(red2("Failed to search organizations"));
|
|
129776
|
+
M22.error(error482 instanceof Error ? error482.message : "Unknown error");
|
|
129777
|
+
return null;
|
|
129778
|
+
}
|
|
129779
|
+
if (results.length === 0) {
|
|
129780
|
+
M22.warn("No organizations found matching your search");
|
|
129781
|
+
return promptOrganization(client);
|
|
129782
|
+
}
|
|
129783
|
+
const validResults = results.filter((org) => org.sourcedId);
|
|
129784
|
+
if (validResults.length === 0) {
|
|
129785
|
+
M22.warn("No valid organizations found (missing IDs)");
|
|
129786
|
+
return promptOrganization(client);
|
|
129787
|
+
}
|
|
129788
|
+
const options = validResults.map((org) => ({
|
|
129789
|
+
value: org.sourcedId,
|
|
129790
|
+
label: org.name ?? "Unnamed Organization"
|
|
129791
|
+
}));
|
|
129792
|
+
options.push({ value: "__back__", label: `${dim2("←")} Back to options` });
|
|
129793
|
+
const selection = await ve2({
|
|
129794
|
+
message: "Select an organization",
|
|
129795
|
+
options
|
|
129796
|
+
});
|
|
129797
|
+
if (isCancelled2(selection))
|
|
129798
|
+
return null;
|
|
129799
|
+
if (selection === "__back__") {
|
|
129800
|
+
return promptOrganization(client);
|
|
129801
|
+
}
|
|
129802
|
+
return validResults.find((org) => org.sourcedId === selection) ?? null;
|
|
129803
|
+
}
|
|
129804
|
+
async function promptOrganization(client) {
|
|
129805
|
+
const action = await ve2({
|
|
129806
|
+
message: "Organization",
|
|
129807
|
+
options: [
|
|
129808
|
+
{ value: "search", label: "Search for existing organization" },
|
|
129809
|
+
{ value: "create", label: "Create new organization" }
|
|
129810
|
+
]
|
|
129811
|
+
});
|
|
129812
|
+
if (isCancelled2(action))
|
|
129813
|
+
return null;
|
|
129814
|
+
if (action === "create") {
|
|
129815
|
+
return createNewOrganization(client);
|
|
129816
|
+
}
|
|
129817
|
+
return searchForOrganization(client);
|
|
129818
|
+
}
|
|
129819
|
+
async function createNewOrganization(client) {
|
|
129820
|
+
const name = await he2({
|
|
129821
|
+
message: "Organization name",
|
|
129822
|
+
placeholder: "Enter organization name",
|
|
129823
|
+
validate: (v2) => {
|
|
129824
|
+
if (!v2?.trim())
|
|
129825
|
+
return "Organization name is required";
|
|
129826
|
+
}
|
|
129827
|
+
});
|
|
129828
|
+
if (isCancelled2(name))
|
|
129829
|
+
return null;
|
|
129830
|
+
const s = Y22();
|
|
129831
|
+
s.start("Creating organization...");
|
|
129832
|
+
const sourcedId = randomUUID();
|
|
129833
|
+
try {
|
|
129834
|
+
await client.oneroster.orgs.create({
|
|
129835
|
+
sourcedId,
|
|
129836
|
+
name: name.trim(),
|
|
129837
|
+
type: "school",
|
|
129838
|
+
status: "active"
|
|
129839
|
+
});
|
|
129840
|
+
const organization = await client.oneroster.orgs.get(sourcedId);
|
|
129841
|
+
s.stop(green2(`Organization "${name}" created`));
|
|
129842
|
+
return organization;
|
|
129843
|
+
} catch (error482) {
|
|
129844
|
+
s.stop(red2("Failed to create organization"));
|
|
129845
|
+
M22.error(error482 instanceof Error ? error482.message : "Unknown error");
|
|
129846
|
+
return null;
|
|
129847
|
+
}
|
|
129848
|
+
}
|
|
129849
|
+
async function createUser(client, email32, givenName, familyName, organizationId) {
|
|
129850
|
+
const s = Y22();
|
|
129851
|
+
s.start("Creating account...");
|
|
129852
|
+
const sourcedId = randomUUID();
|
|
129853
|
+
try {
|
|
129854
|
+
await client.oneroster.users.create({
|
|
129855
|
+
sourcedId,
|
|
129856
|
+
givenName,
|
|
129857
|
+
familyName,
|
|
129858
|
+
email: email32.toLowerCase(),
|
|
129859
|
+
enabledUser: true,
|
|
129860
|
+
status: "active",
|
|
129861
|
+
roles: [
|
|
129862
|
+
{
|
|
129863
|
+
roleType: "primary",
|
|
129864
|
+
role: "administrator",
|
|
129865
|
+
org: { sourcedId: organizationId }
|
|
129866
|
+
}
|
|
129867
|
+
]
|
|
129868
|
+
});
|
|
129869
|
+
const user = await client.oneroster.users.get(sourcedId);
|
|
129870
|
+
s.stop(green2("Account created successfully"));
|
|
129871
|
+
return user;
|
|
129872
|
+
} catch (error482) {
|
|
129873
|
+
s.stop(red2("Failed to create account"));
|
|
129874
|
+
M22.error(error482 instanceof Error ? error482.message : "Unknown error");
|
|
129875
|
+
return null;
|
|
129876
|
+
}
|
|
129877
|
+
}
|
|
129878
|
+
async function createAccountFlow(options) {
|
|
129879
|
+
const { environment, clientId, clientSecret, email: email32 } = options;
|
|
129880
|
+
M22.info("");
|
|
129881
|
+
M22.info(`No account found for ${dim2(email32)} in ${environment}`);
|
|
129882
|
+
const shouldCreate = await ye2({
|
|
129883
|
+
message: "Would you like to create a new account?",
|
|
129884
|
+
initialValue: true
|
|
129885
|
+
});
|
|
129886
|
+
if (isCancelled2(shouldCreate)) {
|
|
129887
|
+
return { success: false };
|
|
129888
|
+
}
|
|
129889
|
+
if (!shouldCreate) {
|
|
129890
|
+
return { success: false, declined: true };
|
|
129891
|
+
}
|
|
129892
|
+
const client = new TimebackClient({
|
|
129893
|
+
env: environment,
|
|
129894
|
+
auth: { clientId, clientSecret }
|
|
129895
|
+
});
|
|
129896
|
+
const givenName = await promptName("First name");
|
|
129897
|
+
if (!givenName)
|
|
129898
|
+
return { success: false };
|
|
129899
|
+
const familyName = await promptName("Last name");
|
|
129900
|
+
if (!familyName)
|
|
129901
|
+
return { success: false };
|
|
129902
|
+
const organization = await promptOrganization(client);
|
|
129903
|
+
if (!organization?.sourcedId)
|
|
129904
|
+
return { success: false };
|
|
129905
|
+
const user = await createUser(client, email32, givenName, familyName, organization.sourcedId);
|
|
129906
|
+
if (!user) {
|
|
129907
|
+
return { success: false };
|
|
129908
|
+
}
|
|
129909
|
+
M22.success(`Account created for ${user.givenName} ${user.familyName}`);
|
|
129910
|
+
return { success: true };
|
|
129911
|
+
}
|
|
129703
129912
|
async function updateEmail2(options = {}) {
|
|
129704
129913
|
const { exitOnComplete = true, inline = false } = options;
|
|
129705
129914
|
const configuredEnvs = [];
|
|
@@ -129767,32 +129976,58 @@ async function updateEmail2(options = {}) {
|
|
|
129767
129976
|
return;
|
|
129768
129977
|
}
|
|
129769
129978
|
const emailUnchanged = email32 === (currentEmail ?? "");
|
|
129770
|
-
if (emailUnchanged) {
|
|
129771
|
-
if (!inline)
|
|
129772
|
-
outro2.info("Email unchanged");
|
|
129773
|
-
if (exitOnComplete)
|
|
129774
|
-
process.exit(0);
|
|
129775
|
-
return;
|
|
129776
|
-
}
|
|
129777
129979
|
if (email32) {
|
|
129778
129980
|
const s = Y22();
|
|
129779
|
-
s.start("
|
|
129981
|
+
s.start("Checking account...");
|
|
129780
129982
|
const result = await validateEmailWithTimeback2(targetEnv, currentCreds.clientId, currentCreds.clientSecret, email32);
|
|
129781
129983
|
if (!result.valid) {
|
|
129782
|
-
|
|
129783
|
-
|
|
129784
|
-
|
|
129984
|
+
if (result.reason !== "not_found") {
|
|
129985
|
+
s.stop(red2("Account check failed"));
|
|
129986
|
+
M22.error(result.error ?? "Unknown error");
|
|
129987
|
+
if (!inline)
|
|
129988
|
+
outro2.error("Account check failed");
|
|
129989
|
+
if (exitOnComplete)
|
|
129990
|
+
process.exit(1);
|
|
129991
|
+
return;
|
|
129992
|
+
}
|
|
129993
|
+
s.stop(red2("No account found"));
|
|
129994
|
+
const { success: accountCreated, declined } = await createAccountFlow({
|
|
129995
|
+
environment: targetEnv,
|
|
129996
|
+
clientId: currentCreds.clientId,
|
|
129997
|
+
clientSecret: currentCreds.clientSecret,
|
|
129998
|
+
email: email32
|
|
129999
|
+
});
|
|
130000
|
+
if (!emailUnchanged) {
|
|
130001
|
+
await saveCredentials2(targetEnv, {
|
|
130002
|
+
...currentCreds,
|
|
130003
|
+
email: email32
|
|
130004
|
+
});
|
|
130005
|
+
M22.success(`Email saved for ${targetEnv}`);
|
|
130006
|
+
}
|
|
130007
|
+
if (!inline) {
|
|
130008
|
+
if (accountCreated || declined) {
|
|
130009
|
+
outro2.success();
|
|
130010
|
+
} else {
|
|
130011
|
+
outro2.info("Setup incomplete - run this command again to finish");
|
|
130012
|
+
}
|
|
130013
|
+
}
|
|
130014
|
+
if (exitOnComplete)
|
|
130015
|
+
process.exit(0);
|
|
130016
|
+
return;
|
|
130017
|
+
}
|
|
130018
|
+
s.stop(green2("Account verified"));
|
|
130019
|
+
if (emailUnchanged) {
|
|
129785
130020
|
if (!inline)
|
|
129786
|
-
outro2.
|
|
130021
|
+
outro2.info("Email unchanged");
|
|
129787
130022
|
if (exitOnComplete)
|
|
129788
|
-
process.exit(
|
|
130023
|
+
process.exit(0);
|
|
129789
130024
|
return;
|
|
129790
130025
|
}
|
|
129791
130026
|
await saveCredentials2(targetEnv, {
|
|
129792
130027
|
...currentCreds,
|
|
129793
130028
|
email: email32
|
|
129794
130029
|
});
|
|
129795
|
-
|
|
130030
|
+
M22.success(`Email updated for ${targetEnv}`);
|
|
129796
130031
|
if (!inline)
|
|
129797
130032
|
outro2.success();
|
|
129798
130033
|
if (exitOnComplete)
|
|
@@ -132385,7 +132620,8 @@ var cors = (options) => {
|
|
|
132385
132620
|
async function handleBootstrap(c, ctx) {
|
|
132386
132621
|
const { bootstrap } = c.get("services");
|
|
132387
132622
|
const env22 = c.get("env");
|
|
132388
|
-
const
|
|
132623
|
+
const freshCredentials = await getSavedCredentials2(env22);
|
|
132624
|
+
const email32 = freshCredentials?.email;
|
|
132389
132625
|
const courseIds = ctx.userConfig.courseIds[env22];
|
|
132390
132626
|
const result = await bootstrap.getBootstrap({ email: email32, courseIds });
|
|
132391
132627
|
return c.json(result);
|
|
@@ -133303,11 +133539,15 @@ class StatusService {
|
|
|
133303
133539
|
}
|
|
133304
133540
|
async getStatus() {
|
|
133305
133541
|
const configuredEnvironments = await getConfiguredEnvironments2();
|
|
133542
|
+
const [stagingCreds, productionCreds] = await Promise.all([
|
|
133543
|
+
getSavedCredentials2("staging"),
|
|
133544
|
+
getSavedCredentials2("production")
|
|
133545
|
+
]);
|
|
133306
133546
|
return {
|
|
133307
133547
|
config: this.ctx.userConfig,
|
|
133308
133548
|
environment: this.ctx.defaultEnvironment,
|
|
133309
133549
|
configuredEnvironments,
|
|
133310
|
-
hasEmail: !!
|
|
133550
|
+
hasEmail: !!stagingCreds?.email || !!productionCreds?.email
|
|
133311
133551
|
};
|
|
133312
133552
|
}
|
|
133313
133553
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "timeback",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"timeback": "./dist/cli.js"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"zod": "^4.2.1"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@timeback/caliper": "0.1.
|
|
28
|
+
"@timeback/caliper": "0.1.4",
|
|
29
29
|
"@timeback/core": "0.1.4",
|
|
30
30
|
"@timeback/edubridge": "0.1.3",
|
|
31
31
|
"@timeback/internal-cli-infra": "0.0.0",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@timeback/types": "0.0.0",
|
|
38
38
|
"@types/bun": "latest",
|
|
39
39
|
"bun-plugin-dts": "^0.3.0",
|
|
40
|
-
"timeback-studio": "0.1.
|
|
40
|
+
"timeback-studio": "0.1.7"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"typescript": "^5"
|