timeback-studio 0.1.5 → 0.1.6
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/bin.js +74 -31
- package/dist/cli/commands/credentials/add.d.ts.map +1 -1
- package/dist/cli/commands/credentials/lib/initial.d.ts +1 -1
- package/dist/cli/commands/credentials/lib/initial.d.ts.map +1 -1
- package/dist/cli/commands/serve/config.d.ts +1 -1
- package/dist/cli/commands/serve/config.d.ts.map +1 -1
- package/dist/cli/commands/serve/index.d.ts.map +1 -1
- package/dist/index.js +74 -31
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -2950,6 +2950,11 @@ ${t}
|
|
|
2950
2950
|
${import_picocolors2.default.green(C)} ${import_picocolors2.default.reset(n)} ${import_picocolors2.default.gray(_2.repeat(Math.max(s - i - 1, 1)) + me)}
|
|
2951
2951
|
${c}
|
|
2952
2952
|
${import_picocolors2.default.gray(de + _2.repeat(s + 2) + pe)}
|
|
2953
|
+
`);
|
|
2954
|
+
};
|
|
2955
|
+
var xe = (t = "") => {
|
|
2956
|
+
process.stdout.write(`${import_picocolors2.default.gray(d2)} ${import_picocolors2.default.red(t)}
|
|
2957
|
+
|
|
2953
2958
|
`);
|
|
2954
2959
|
};
|
|
2955
2960
|
var Ie = (t = "") => {
|
|
@@ -16695,7 +16700,7 @@ function intro(title) {
|
|
|
16695
16700
|
}
|
|
16696
16701
|
var outro = {
|
|
16697
16702
|
success: (message = "Done") => Se(green(message)),
|
|
16698
|
-
cancelled: () =>
|
|
16703
|
+
cancelled: () => xe(dim("Cancelled")),
|
|
16699
16704
|
error: (message) => Se(red(message)),
|
|
16700
16705
|
warn: (message) => Se(yellow(message)),
|
|
16701
16706
|
info: (message) => Se(dim(message))
|
|
@@ -16795,8 +16800,8 @@ async function getConfiguredEnvironments() {
|
|
|
16795
16800
|
return configured;
|
|
16796
16801
|
}
|
|
16797
16802
|
function getEnvCredentials() {
|
|
16798
|
-
const clientId = process.env.TIMEBACK_CLIENT_ID;
|
|
16799
|
-
const clientSecret = process.env.TIMEBACK_CLIENT_SECRET;
|
|
16803
|
+
const clientId = process.env.TIMEBACK_API_CLIENT_ID ?? process.env.TIMEBACK_CLIENT_ID;
|
|
16804
|
+
const clientSecret = process.env.TIMEBACK_API_CLIENT_SECRET ?? process.env.TIMEBACK_CLIENT_SECRET;
|
|
16800
16805
|
if (clientId && clientSecret) {
|
|
16801
16806
|
const result = CredentialsSchema.safeParse({ clientId, clientSecret });
|
|
16802
16807
|
if (result.success) {
|
|
@@ -16840,7 +16845,10 @@ async function validateEmailWithTimeback(environment, clientId, clientSecret, em
|
|
|
16840
16845
|
});
|
|
16841
16846
|
try {
|
|
16842
16847
|
const page = await client.oneroster.users.list({
|
|
16843
|
-
where: {
|
|
16848
|
+
where: {
|
|
16849
|
+
email: email3,
|
|
16850
|
+
status: "active"
|
|
16851
|
+
},
|
|
16844
16852
|
limit: 1
|
|
16845
16853
|
});
|
|
16846
16854
|
if (page.data.length === 0) {
|
|
@@ -16868,7 +16876,7 @@ async function promptForCredentials(environment) {
|
|
|
16868
16876
|
}
|
|
16869
16877
|
});
|
|
16870
16878
|
if (isCancelled(clientId))
|
|
16871
|
-
return
|
|
16879
|
+
return { status: "cancelled" };
|
|
16872
16880
|
const clientSecret = await ge({
|
|
16873
16881
|
message: `Client Secret ${dim(`(${environment})`)}`,
|
|
16874
16882
|
validate: (value) => {
|
|
@@ -16878,7 +16886,7 @@ async function promptForCredentials(environment) {
|
|
|
16878
16886
|
}
|
|
16879
16887
|
});
|
|
16880
16888
|
if (isCancelled(clientSecret))
|
|
16881
|
-
return
|
|
16889
|
+
return { status: "cancelled" };
|
|
16882
16890
|
const email3 = await he({
|
|
16883
16891
|
message: `Your email ${dim("(for fetching your OneRoster profile)")}`,
|
|
16884
16892
|
placeholder: "you@example.com",
|
|
@@ -16891,33 +16899,47 @@ async function promptForCredentials(environment) {
|
|
|
16891
16899
|
}
|
|
16892
16900
|
});
|
|
16893
16901
|
if (isCancelled(email3))
|
|
16894
|
-
return
|
|
16902
|
+
return { status: "cancelled" };
|
|
16895
16903
|
if (email3) {
|
|
16896
16904
|
const s = Y2();
|
|
16897
16905
|
s.start("Validating email...");
|
|
16898
16906
|
const result = await validateEmailWithTimeback(environment, clientId, clientSecret, email3);
|
|
16899
16907
|
if (!result.valid) {
|
|
16900
|
-
|
|
16901
|
-
|
|
16908
|
+
const errorMsg = result.error ?? "Email validation failed";
|
|
16909
|
+
s.stop(red(errorMsg));
|
|
16902
16910
|
M2.info("Please contact a Timeback admin to set up your account.");
|
|
16903
|
-
return
|
|
16911
|
+
return {
|
|
16912
|
+
status: "error",
|
|
16913
|
+
error: errorMsg
|
|
16914
|
+
};
|
|
16904
16915
|
}
|
|
16905
16916
|
s.stop(green("Email validated"));
|
|
16906
16917
|
}
|
|
16907
|
-
return {
|
|
16918
|
+
return {
|
|
16919
|
+
status: "ok",
|
|
16920
|
+
credentials: { clientId, clientSecret, email: email3 || undefined }
|
|
16921
|
+
};
|
|
16908
16922
|
}
|
|
16909
16923
|
async function ensureCredentials(options) {
|
|
16910
16924
|
const { env: env2, credentials, introTitle = "Timeback", skipIntro = false } = options;
|
|
16911
16925
|
const existing = credentials[env2];
|
|
16912
|
-
if (existing)
|
|
16913
|
-
return existing;
|
|
16926
|
+
if (existing) {
|
|
16927
|
+
return { status: "ok", credentials: existing, source: "existing" };
|
|
16928
|
+
}
|
|
16914
16929
|
if (!skipIntro) {
|
|
16915
16930
|
intro(introTitle);
|
|
16916
16931
|
}
|
|
16917
16932
|
Me(`No credentials configured for ${env2}.`, "Credential setup required");
|
|
16918
|
-
const
|
|
16919
|
-
if (
|
|
16920
|
-
|
|
16933
|
+
const promptResult = await promptForCredentials(env2);
|
|
16934
|
+
if (promptResult.status === "cancelled") {
|
|
16935
|
+
outro.cancelled();
|
|
16936
|
+
return { status: "cancelled" };
|
|
16937
|
+
}
|
|
16938
|
+
if (promptResult.status === "error") {
|
|
16939
|
+
outro.error("Credential setup failed");
|
|
16940
|
+
return { status: "error", error: promptResult.error };
|
|
16941
|
+
}
|
|
16942
|
+
const newCreds = promptResult.credentials;
|
|
16921
16943
|
const saved = await saveCredentials(env2, newCreds);
|
|
16922
16944
|
if (saved) {
|
|
16923
16945
|
M2.success(`${env2} credentials saved`);
|
|
@@ -16926,7 +16948,7 @@ async function ensureCredentials(options) {
|
|
|
16926
16948
|
M2.warn(`Credentials not saved`);
|
|
16927
16949
|
}
|
|
16928
16950
|
credentials[env2] = newCreds;
|
|
16929
|
-
return newCreds;
|
|
16951
|
+
return { status: "ok", credentials: newCreds, source: "prompted" };
|
|
16930
16952
|
}
|
|
16931
16953
|
// ../internal/cli-infra/src/config/playcademy.ts
|
|
16932
16954
|
var FILE_PATTERNS = ["playcademy.config.ts", "playcademy.config.js", "playcademy.config.json"];
|
|
@@ -19408,8 +19430,8 @@ async function addCredentials(options = {}) {
|
|
|
19408
19430
|
}
|
|
19409
19431
|
isOverwriting = true;
|
|
19410
19432
|
}
|
|
19411
|
-
const
|
|
19412
|
-
if (
|
|
19433
|
+
const result = await promptForCredentials(env2);
|
|
19434
|
+
if (result.status === "cancelled") {
|
|
19413
19435
|
if (!inline) {
|
|
19414
19436
|
if (isOverwriting) {
|
|
19415
19437
|
outro.info("Existing credentials unchanged");
|
|
@@ -19417,11 +19439,21 @@ async function addCredentials(options = {}) {
|
|
|
19417
19439
|
outro.cancelled();
|
|
19418
19440
|
}
|
|
19419
19441
|
}
|
|
19420
|
-
if (exitOnComplete)
|
|
19442
|
+
if (exitOnComplete) {
|
|
19421
19443
|
process.exit(0);
|
|
19444
|
+
}
|
|
19445
|
+
return;
|
|
19446
|
+
}
|
|
19447
|
+
if (result.status === "error") {
|
|
19448
|
+
if (!inline) {
|
|
19449
|
+
outro.error("Credential setup failed");
|
|
19450
|
+
}
|
|
19451
|
+
if (exitOnComplete) {
|
|
19452
|
+
process.exit(1);
|
|
19453
|
+
}
|
|
19422
19454
|
return;
|
|
19423
19455
|
}
|
|
19424
|
-
await saveCredentials(env2,
|
|
19456
|
+
await saveCredentials(env2, result.credentials);
|
|
19425
19457
|
M2.success(`${env2} credentials saved`);
|
|
19426
19458
|
savedCount++;
|
|
19427
19459
|
}
|
|
@@ -19688,14 +19720,21 @@ async function promptInitialCredentials(options = {}) {
|
|
|
19688
19720
|
outro.cancelled();
|
|
19689
19721
|
process.exit(0);
|
|
19690
19722
|
}
|
|
19723
|
+
const configuredEnvs = [];
|
|
19691
19724
|
for (const env2 of environments) {
|
|
19692
|
-
const
|
|
19693
|
-
if (
|
|
19694
|
-
|
|
19695
|
-
|
|
19725
|
+
const result = await promptForCredentials(env2);
|
|
19726
|
+
if (result.status === "cancelled") {
|
|
19727
|
+
outro.cancelled();
|
|
19728
|
+
process.exit(0);
|
|
19696
19729
|
}
|
|
19730
|
+
if (result.status === "error") {
|
|
19731
|
+
outro.error("Credential setup failed");
|
|
19732
|
+
process.exit(1);
|
|
19733
|
+
}
|
|
19734
|
+
await saveCredentials(env2, result.credentials);
|
|
19735
|
+
M2.success(`${env2} credentials saved`);
|
|
19736
|
+
configuredEnvs.push(env2);
|
|
19697
19737
|
}
|
|
19698
|
-
const configuredEnvs = environments;
|
|
19699
19738
|
let selectedEnv;
|
|
19700
19739
|
if (configuredEnvs.length === 1) {
|
|
19701
19740
|
selectedEnv = configuredEnvs[0];
|
|
@@ -20058,10 +20097,11 @@ function buildUserConfigFromCourses(courses) {
|
|
|
20058
20097
|
};
|
|
20059
20098
|
}
|
|
20060
20099
|
async function resolveFromCourseIds(courseIds, env2, credentials, configuredEnvs) {
|
|
20061
|
-
const
|
|
20062
|
-
if (
|
|
20100
|
+
const ensureResult = await ensureCredentials({ env: env2, credentials, skipIntro: true });
|
|
20101
|
+
if (ensureResult.status !== "ok") {
|
|
20063
20102
|
return null;
|
|
20064
20103
|
}
|
|
20104
|
+
const creds = ensureResult.credentials;
|
|
20065
20105
|
const courses = await fetchCourses(creds, env2, courseIds);
|
|
20066
20106
|
if (courses.length === 0) {
|
|
20067
20107
|
M2.warn("No courses found for the provided IDs.");
|
|
@@ -23440,7 +23480,6 @@ function createEnvMiddleware(ctx, manager) {
|
|
|
23440
23480
|
}, 400);
|
|
23441
23481
|
}
|
|
23442
23482
|
if (!manager.has(env2)) {
|
|
23443
|
-
log7.warn("Environment not configured", { env: env2 });
|
|
23444
23483
|
const error48 = createStudioError("ENV_NOT_CONFIGURED", `Environment '${env2}' not configured`);
|
|
23445
23484
|
return c.json({
|
|
23446
23485
|
success: false,
|
|
@@ -23970,10 +24009,14 @@ function startServer(ctx, serverConfig, configFile) {
|
|
|
23970
24009
|
|
|
23971
24010
|
// src/cli/commands/serve/index.ts
|
|
23972
24011
|
async function launchServer(serverConfig, userConfig, credentials, env2, opts, configFile) {
|
|
23973
|
-
const
|
|
23974
|
-
if (
|
|
24012
|
+
const ensureResult = await ensureCredentials({ env: env2, credentials, skipIntro: true });
|
|
24013
|
+
if (ensureResult.status === "cancelled") {
|
|
24014
|
+
process.exit(0);
|
|
24015
|
+
}
|
|
24016
|
+
if (ensureResult.status === "error") {
|
|
23975
24017
|
process.exit(1);
|
|
23976
24018
|
}
|
|
24019
|
+
const creds = ensureResult.credentials;
|
|
23977
24020
|
const derivedSensors = await resolveSensors({
|
|
23978
24021
|
config: userConfig,
|
|
23979
24022
|
env: env2,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/credentials/add.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAE3C;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/credentials/add.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAE3C;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuFhF"}
|
|
@@ -7,7 +7,7 @@ interface PromptInitialCredentialsOptions {
|
|
|
7
7
|
* Runs the first-time credential setup flow.
|
|
8
8
|
*
|
|
9
9
|
* @param options - Options for the prompt
|
|
10
|
-
* @returns The selected environment to use for this run, or null if cancelled
|
|
10
|
+
* @returns The selected environment to use for this run, or null if cancelled/error
|
|
11
11
|
*/
|
|
12
12
|
export declare function promptInitialCredentials(options?: PromptInitialCredentialsOptions): Promise<CredentialEnvironment | null>;
|
|
13
13
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initial.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/credentials/lib/initial.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AAEzE,UAAU,+BAA+B;IACxC,kEAAkE;IAClE,SAAS,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC7C,OAAO,GAAE,+BAAoC,GAC3C,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"initial.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/credentials/lib/initial.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AAEzE,UAAU,+BAA+B;IACxC,kEAAkE;IAClE,SAAS,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC7C,OAAO,GAAE,+BAAoC,GAC3C,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAoEvC"}
|
|
@@ -42,7 +42,7 @@ export declare function buildUserConfigFromCourses(courses: CourseConfig[]): Loa
|
|
|
42
42
|
* @param env - Target environment
|
|
43
43
|
* @param credentials - Credentials map
|
|
44
44
|
* @param configuredEnvs - List of configured environments
|
|
45
|
-
* @returns Resolved config, or null if cancelled
|
|
45
|
+
* @returns Resolved config, or null if cancelled/error
|
|
46
46
|
*/
|
|
47
47
|
export declare function resolveFromCourseIds(courseIds: string[], env: Environment, credentials: EnvironmentCredentials, configuredEnvs: Environment[]): Promise<ResolvedConfig | null>;
|
|
48
48
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/serve/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AA0BH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,KAAK,EACX,WAAW,EACX,WAAW,EACX,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,EACb,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3D,UAAU,yBAAyB;IAClC,QAAQ,EAAE,cAAc,CAAA;IACxB,WAAW,EAAE,sBAAsB,CAAA;IACnC,cAAc,EAAE,WAAW,EAAE,CAAA;CAC7B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACxC,SAAS,EAAE,MAAM,EAAE,EACnB,IAAI,EAAE,YAAY,EAClB,kBAAkB,EAAE,WAAW,GAC7B,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAqF3C;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,YAAY,GAAG,gBAAgB,CAqBhF;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,gBAAgB,CAkBpF;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACzC,SAAS,EAAE,MAAM,EAAE,EACnB,GAAG,EAAE,WAAW,EAChB,WAAW,EAAE,sBAAsB,EACnC,cAAc,EAAE,WAAW,EAAE,GAC3B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/serve/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AA0BH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,KAAK,EACX,WAAW,EACX,WAAW,EACX,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,EACb,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3D,UAAU,yBAAyB;IAClC,QAAQ,EAAE,cAAc,CAAA;IACxB,WAAW,EAAE,sBAAsB,CAAA;IACnC,cAAc,EAAE,WAAW,EAAE,CAAA;CAC7B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACxC,SAAS,EAAE,MAAM,EAAE,EACnB,IAAI,EAAE,YAAY,EAClB,kBAAkB,EAAE,WAAW,GAC7B,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAqF3C;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,YAAY,GAAG,gBAAgB,CAqBhF;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,gBAAgB,CAkBpF;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACzC,SAAS,EAAE,MAAM,EAAE,EACnB,GAAG,EAAE,WAAW,EAChB,WAAW,EAAE,sBAAsB,EACnC,cAAc,EAAE,WAAW,EAAE,GAC3B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAgChC;AAED;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC9C,WAAW,EAAE,sBAAsB,EACnC,cAAc,EAAE,WAAW,EAAE,EAC7B,UAAU,EAAE,WAAW,EACvB,UAAU,GAAE,aAAkB,GAC5B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA0BhC;AAmCD;;;;;;;;;GASG;AACH;;GAEG;AACH,UAAU,qBAAqB;IAC9B,MAAM,EAAE,gBAAgB,CAAA;IACxB,GAAG,EAAE,WAAW,CAAA;IAChB,IAAI,EAAE,YAAY,CAAA;IAClB,KAAK,EAAE,WAAW,CAAA;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,cAAc,CACnC,OAAO,EAAE,qBAAqB,GAC5B,OAAO,CAAC,MAAM,EAAE,GAAG,SAAS,GAAG,IAAI,CAAC,CA2EtC;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,aAAa,CAClC,SAAS,EAAE,MAAM,EAAE,EACnB,IAAI,EAAE,YAAY,EAClB,WAAW,EAAE,sBAAsB,EACnC,cAAc,EAAE,WAAW,EAAE,EAC7B,UAAU,EAAE,WAAW,GACrB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAShC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/serve/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAmBH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/serve/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAmBH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AA0M3C;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCzF"}
|
package/dist/index.js
CHANGED
|
@@ -840,6 +840,11 @@ ${t}
|
|
|
840
840
|
${import_picocolors2.default.green(C)} ${import_picocolors2.default.reset(n)} ${import_picocolors2.default.gray(_2.repeat(Math.max(s - i - 1, 1)) + me)}
|
|
841
841
|
${c}
|
|
842
842
|
${import_picocolors2.default.gray(de + _2.repeat(s + 2) + pe)}
|
|
843
|
+
`);
|
|
844
|
+
};
|
|
845
|
+
var xe = (t = "") => {
|
|
846
|
+
process.stdout.write(`${import_picocolors2.default.gray(d2)} ${import_picocolors2.default.red(t)}
|
|
847
|
+
|
|
843
848
|
`);
|
|
844
849
|
};
|
|
845
850
|
var Ie = (t = "") => {
|
|
@@ -14585,7 +14590,7 @@ function intro(title) {
|
|
|
14585
14590
|
}
|
|
14586
14591
|
var outro = {
|
|
14587
14592
|
success: (message = "Done") => Se(green(message)),
|
|
14588
|
-
cancelled: () =>
|
|
14593
|
+
cancelled: () => xe(dim("Cancelled")),
|
|
14589
14594
|
error: (message) => Se(red(message)),
|
|
14590
14595
|
warn: (message) => Se(yellow(message)),
|
|
14591
14596
|
info: (message) => Se(dim(message))
|
|
@@ -14685,8 +14690,8 @@ async function getConfiguredEnvironments() {
|
|
|
14685
14690
|
return configured;
|
|
14686
14691
|
}
|
|
14687
14692
|
function getEnvCredentials() {
|
|
14688
|
-
const clientId = process.env.TIMEBACK_CLIENT_ID;
|
|
14689
|
-
const clientSecret = process.env.TIMEBACK_CLIENT_SECRET;
|
|
14693
|
+
const clientId = process.env.TIMEBACK_API_CLIENT_ID ?? process.env.TIMEBACK_CLIENT_ID;
|
|
14694
|
+
const clientSecret = process.env.TIMEBACK_API_CLIENT_SECRET ?? process.env.TIMEBACK_CLIENT_SECRET;
|
|
14690
14695
|
if (clientId && clientSecret) {
|
|
14691
14696
|
const result = CredentialsSchema.safeParse({ clientId, clientSecret });
|
|
14692
14697
|
if (result.success) {
|
|
@@ -14730,7 +14735,10 @@ async function validateEmailWithTimeback(environment, clientId, clientSecret, em
|
|
|
14730
14735
|
});
|
|
14731
14736
|
try {
|
|
14732
14737
|
const page = await client.oneroster.users.list({
|
|
14733
|
-
where: {
|
|
14738
|
+
where: {
|
|
14739
|
+
email: email3,
|
|
14740
|
+
status: "active"
|
|
14741
|
+
},
|
|
14734
14742
|
limit: 1
|
|
14735
14743
|
});
|
|
14736
14744
|
if (page.data.length === 0) {
|
|
@@ -14758,7 +14766,7 @@ async function promptForCredentials(environment) {
|
|
|
14758
14766
|
}
|
|
14759
14767
|
});
|
|
14760
14768
|
if (isCancelled(clientId))
|
|
14761
|
-
return
|
|
14769
|
+
return { status: "cancelled" };
|
|
14762
14770
|
const clientSecret = await ge({
|
|
14763
14771
|
message: `Client Secret ${dim(`(${environment})`)}`,
|
|
14764
14772
|
validate: (value) => {
|
|
@@ -14768,7 +14776,7 @@ async function promptForCredentials(environment) {
|
|
|
14768
14776
|
}
|
|
14769
14777
|
});
|
|
14770
14778
|
if (isCancelled(clientSecret))
|
|
14771
|
-
return
|
|
14779
|
+
return { status: "cancelled" };
|
|
14772
14780
|
const email3 = await he({
|
|
14773
14781
|
message: `Your email ${dim("(for fetching your OneRoster profile)")}`,
|
|
14774
14782
|
placeholder: "you@example.com",
|
|
@@ -14781,33 +14789,47 @@ async function promptForCredentials(environment) {
|
|
|
14781
14789
|
}
|
|
14782
14790
|
});
|
|
14783
14791
|
if (isCancelled(email3))
|
|
14784
|
-
return
|
|
14792
|
+
return { status: "cancelled" };
|
|
14785
14793
|
if (email3) {
|
|
14786
14794
|
const s = Y2();
|
|
14787
14795
|
s.start("Validating email...");
|
|
14788
14796
|
const result = await validateEmailWithTimeback(environment, clientId, clientSecret, email3);
|
|
14789
14797
|
if (!result.valid) {
|
|
14790
|
-
|
|
14791
|
-
|
|
14798
|
+
const errorMsg = result.error ?? "Email validation failed";
|
|
14799
|
+
s.stop(red(errorMsg));
|
|
14792
14800
|
M2.info("Please contact a Timeback admin to set up your account.");
|
|
14793
|
-
return
|
|
14801
|
+
return {
|
|
14802
|
+
status: "error",
|
|
14803
|
+
error: errorMsg
|
|
14804
|
+
};
|
|
14794
14805
|
}
|
|
14795
14806
|
s.stop(green("Email validated"));
|
|
14796
14807
|
}
|
|
14797
|
-
return {
|
|
14808
|
+
return {
|
|
14809
|
+
status: "ok",
|
|
14810
|
+
credentials: { clientId, clientSecret, email: email3 || undefined }
|
|
14811
|
+
};
|
|
14798
14812
|
}
|
|
14799
14813
|
async function ensureCredentials(options) {
|
|
14800
14814
|
const { env: env2, credentials, introTitle = "Timeback", skipIntro = false } = options;
|
|
14801
14815
|
const existing = credentials[env2];
|
|
14802
|
-
if (existing)
|
|
14803
|
-
return existing;
|
|
14816
|
+
if (existing) {
|
|
14817
|
+
return { status: "ok", credentials: existing, source: "existing" };
|
|
14818
|
+
}
|
|
14804
14819
|
if (!skipIntro) {
|
|
14805
14820
|
intro(introTitle);
|
|
14806
14821
|
}
|
|
14807
14822
|
Me(`No credentials configured for ${env2}.`, "Credential setup required");
|
|
14808
|
-
const
|
|
14809
|
-
if (
|
|
14810
|
-
|
|
14823
|
+
const promptResult = await promptForCredentials(env2);
|
|
14824
|
+
if (promptResult.status === "cancelled") {
|
|
14825
|
+
outro.cancelled();
|
|
14826
|
+
return { status: "cancelled" };
|
|
14827
|
+
}
|
|
14828
|
+
if (promptResult.status === "error") {
|
|
14829
|
+
outro.error("Credential setup failed");
|
|
14830
|
+
return { status: "error", error: promptResult.error };
|
|
14831
|
+
}
|
|
14832
|
+
const newCreds = promptResult.credentials;
|
|
14811
14833
|
const saved = await saveCredentials(env2, newCreds);
|
|
14812
14834
|
if (saved) {
|
|
14813
14835
|
M2.success(`${env2} credentials saved`);
|
|
@@ -14816,7 +14838,7 @@ async function ensureCredentials(options) {
|
|
|
14816
14838
|
M2.warn(`Credentials not saved`);
|
|
14817
14839
|
}
|
|
14818
14840
|
credentials[env2] = newCreds;
|
|
14819
|
-
return newCreds;
|
|
14841
|
+
return { status: "ok", credentials: newCreds, source: "prompted" };
|
|
14820
14842
|
}
|
|
14821
14843
|
// ../internal/cli-infra/src/config/playcademy.ts
|
|
14822
14844
|
var FILE_PATTERNS = ["playcademy.config.ts", "playcademy.config.js", "playcademy.config.json"];
|
|
@@ -17483,8 +17505,8 @@ async function addCredentials(options = {}) {
|
|
|
17483
17505
|
}
|
|
17484
17506
|
isOverwriting = true;
|
|
17485
17507
|
}
|
|
17486
|
-
const
|
|
17487
|
-
if (
|
|
17508
|
+
const result = await promptForCredentials(env2);
|
|
17509
|
+
if (result.status === "cancelled") {
|
|
17488
17510
|
if (!inline) {
|
|
17489
17511
|
if (isOverwriting) {
|
|
17490
17512
|
outro.info("Existing credentials unchanged");
|
|
@@ -17492,11 +17514,21 @@ async function addCredentials(options = {}) {
|
|
|
17492
17514
|
outro.cancelled();
|
|
17493
17515
|
}
|
|
17494
17516
|
}
|
|
17495
|
-
if (exitOnComplete)
|
|
17517
|
+
if (exitOnComplete) {
|
|
17496
17518
|
process.exit(0);
|
|
17519
|
+
}
|
|
17520
|
+
return;
|
|
17521
|
+
}
|
|
17522
|
+
if (result.status === "error") {
|
|
17523
|
+
if (!inline) {
|
|
17524
|
+
outro.error("Credential setup failed");
|
|
17525
|
+
}
|
|
17526
|
+
if (exitOnComplete) {
|
|
17527
|
+
process.exit(1);
|
|
17528
|
+
}
|
|
17497
17529
|
return;
|
|
17498
17530
|
}
|
|
17499
|
-
await saveCredentials(env2,
|
|
17531
|
+
await saveCredentials(env2, result.credentials);
|
|
17500
17532
|
M2.success(`${env2} credentials saved`);
|
|
17501
17533
|
savedCount++;
|
|
17502
17534
|
}
|
|
@@ -17763,14 +17795,21 @@ async function promptInitialCredentials(options = {}) {
|
|
|
17763
17795
|
outro.cancelled();
|
|
17764
17796
|
process.exit(0);
|
|
17765
17797
|
}
|
|
17798
|
+
const configuredEnvs = [];
|
|
17766
17799
|
for (const env2 of environments) {
|
|
17767
|
-
const
|
|
17768
|
-
if (
|
|
17769
|
-
|
|
17770
|
-
|
|
17800
|
+
const result = await promptForCredentials(env2);
|
|
17801
|
+
if (result.status === "cancelled") {
|
|
17802
|
+
outro.cancelled();
|
|
17803
|
+
process.exit(0);
|
|
17771
17804
|
}
|
|
17805
|
+
if (result.status === "error") {
|
|
17806
|
+
outro.error("Credential setup failed");
|
|
17807
|
+
process.exit(1);
|
|
17808
|
+
}
|
|
17809
|
+
await saveCredentials(env2, result.credentials);
|
|
17810
|
+
M2.success(`${env2} credentials saved`);
|
|
17811
|
+
configuredEnvs.push(env2);
|
|
17772
17812
|
}
|
|
17773
|
-
const configuredEnvs = environments;
|
|
17774
17813
|
let selectedEnv;
|
|
17775
17814
|
if (configuredEnvs.length === 1) {
|
|
17776
17815
|
selectedEnv = configuredEnvs[0];
|
|
@@ -17948,10 +17987,11 @@ function buildUserConfigFromCourses(courses) {
|
|
|
17948
17987
|
};
|
|
17949
17988
|
}
|
|
17950
17989
|
async function resolveFromCourseIds(courseIds, env2, credentials, configuredEnvs) {
|
|
17951
|
-
const
|
|
17952
|
-
if (
|
|
17990
|
+
const ensureResult = await ensureCredentials({ env: env2, credentials, skipIntro: true });
|
|
17991
|
+
if (ensureResult.status !== "ok") {
|
|
17953
17992
|
return null;
|
|
17954
17993
|
}
|
|
17994
|
+
const creds = ensureResult.credentials;
|
|
17955
17995
|
const courses = await fetchCourses(creds, env2, courseIds);
|
|
17956
17996
|
if (courses.length === 0) {
|
|
17957
17997
|
M2.warn("No courses found for the provided IDs.");
|
|
@@ -21330,7 +21370,6 @@ function createEnvMiddleware(ctx, manager) {
|
|
|
21330
21370
|
}, 400);
|
|
21331
21371
|
}
|
|
21332
21372
|
if (!manager.has(env2)) {
|
|
21333
|
-
log7.warn("Environment not configured", { env: env2 });
|
|
21334
21373
|
const error48 = createStudioError("ENV_NOT_CONFIGURED", `Environment '${env2}' not configured`);
|
|
21335
21374
|
return c.json({
|
|
21336
21375
|
success: false,
|
|
@@ -21860,10 +21899,14 @@ function startServer(ctx, serverConfig, configFile) {
|
|
|
21860
21899
|
|
|
21861
21900
|
// src/cli/commands/serve/index.ts
|
|
21862
21901
|
async function launchServer(serverConfig, userConfig, credentials, env2, opts, configFile) {
|
|
21863
|
-
const
|
|
21864
|
-
if (
|
|
21902
|
+
const ensureResult = await ensureCredentials({ env: env2, credentials, skipIntro: true });
|
|
21903
|
+
if (ensureResult.status === "cancelled") {
|
|
21904
|
+
process.exit(0);
|
|
21905
|
+
}
|
|
21906
|
+
if (ensureResult.status === "error") {
|
|
21865
21907
|
process.exit(1);
|
|
21866
21908
|
}
|
|
21909
|
+
const creds = ensureResult.credentials;
|
|
21867
21910
|
const derivedSensors = await resolveSensors({
|
|
21868
21911
|
config: userConfig,
|
|
21869
21912
|
env: env2,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "timeback-studio",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@clack/prompts": "^0.11.0",
|
|
29
29
|
"@hono/node-server": "^1.19.7",
|
|
30
|
-
"@timeback/core": "0.1.
|
|
30
|
+
"@timeback/core": "0.1.4",
|
|
31
31
|
"c12": "^3.3.3",
|
|
32
32
|
"colorette": "^2.0.20",
|
|
33
33
|
"commander": "^14.0.2",
|