@uns-kit/core 0.0.31 → 0.0.33
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/config/app-config.d.ts +28 -4
- package/dist/config/app-config.d.ts.map +1 -1
- package/dist/config/app-config.js.map +1 -1
- package/dist/tools/auth/auth-client.d.ts.map +1 -1
- package/dist/tools/auth/auth-client.js +14 -1
- package/dist/tools/auth/auth-client.js.map +1 -1
- package/dist/uns-config/uns-core-schema.d.ts +4 -4
- package/package.json +1 -1
|
@@ -2,6 +2,34 @@ export interface ProjectAppConfig {
|
|
|
2
2
|
uns: {
|
|
3
3
|
graphql: string;
|
|
4
4
|
rest: string;
|
|
5
|
+
/** Email used when authenticating to graphql endpoint of the UNS instance. */
|
|
6
|
+
email: string;
|
|
7
|
+
/** Password or secret value paired with the UNS email. */
|
|
8
|
+
password: string | ({
|
|
9
|
+
/** Load the secret from an environment variable. */
|
|
10
|
+
provider: "env";
|
|
11
|
+
/** Name of the environment variable to read. */
|
|
12
|
+
key: string;
|
|
13
|
+
/** Allow the variable to be absent without throwing during resolution. */
|
|
14
|
+
optional?: boolean | undefined;
|
|
15
|
+
/** Fallback value when optional is true and the variable is missing. */
|
|
16
|
+
default?: string | undefined;
|
|
17
|
+
} | {
|
|
18
|
+
/** Load the secret from Infisical. */
|
|
19
|
+
provider: "infisical";
|
|
20
|
+
/** Secret folder path in Infisical, e.g. '/app/database'. */
|
|
21
|
+
path: string;
|
|
22
|
+
/** Secret key/name inside the given path. */
|
|
23
|
+
key: string;
|
|
24
|
+
/** Allow the secret to be absent without throwing during resolution. */
|
|
25
|
+
optional?: boolean | undefined;
|
|
26
|
+
/** Infisical environment override (defaults to current mode if omitted). */
|
|
27
|
+
environment?: string | undefined;
|
|
28
|
+
/** Optional Infisical project identifier when not using the default. */
|
|
29
|
+
projectId?: string | undefined;
|
|
30
|
+
/** Fallback value when the secret is missing and optional resolution is allowed. */
|
|
31
|
+
default?: string | undefined;
|
|
32
|
+
});
|
|
5
33
|
instanceMode?: "wait" | "force" | "handover";
|
|
6
34
|
processName?: string | undefined;
|
|
7
35
|
handover?: boolean;
|
|
@@ -35,8 +63,4 @@ export interface ProjectAppConfig {
|
|
|
35
63
|
}
|
|
36
64
|
export interface AppConfig extends ProjectAppConfig {
|
|
37
65
|
}
|
|
38
|
-
declare module "@uns-kit/core/config/app-config.js" {
|
|
39
|
-
interface AppConfig extends ProjectAppConfig {
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
66
|
//# sourceMappingURL=app-config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-config.d.ts","sourceRoot":"","sources":["../../src/config/app-config.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,gBAAgB;IAC7B,GAAG,EAAE;QACD,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;QAC7C,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACtC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACrC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;KAC7C,CAAC;IACF,KAAK,CAAC,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KACjC,GAAG,SAAS,CAAC;IACd,MAAM,CAAC,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KACjC,GAAG,SAAS,CAAC;IACd,KAAK,EAAE;QACH,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KACjC,CAAC;IACF,MAAM,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,cAAc,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAChC,GAAG,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,SAAU,SAAQ,gBAAgB;CAAG
|
|
1
|
+
{"version":3,"file":"app-config.d.ts","sourceRoot":"","sources":["../../src/config/app-config.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,gBAAgB;IAC7B,GAAG,EAAE;QACD,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,8EAA8E;QAC9E,KAAK,EAAE,MAAM,CAAC;QACd,0DAA0D;QAC1D,QAAQ,EAAE,MAAM,GAAG,CAAC;YAChB,oDAAoD;YACpD,QAAQ,EAAE,KAAK,CAAC;YAChB,gDAAgD;YAChD,GAAG,EAAE,MAAM,CAAC;YACZ,0EAA0E;YAC1E,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;YAC/B,wEAAwE;YACxE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;SAChC,GAAG;YACA,sCAAsC;YACtC,QAAQ,EAAE,WAAW,CAAC;YACtB,6DAA6D;YAC7D,IAAI,EAAE,MAAM,CAAC;YACb,6CAA6C;YAC7C,GAAG,EAAE,MAAM,CAAC;YACZ,wEAAwE;YACxE,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;YAC/B,4EAA4E;YAC5E,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;YACjC,wEAAwE;YACxE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;YAC/B,oFAAoF;YACpF,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;SAChC,CAAC,CAAC;QACH,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;QAC7C,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACtC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACrC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;KAC7C,CAAC;IACF,KAAK,CAAC,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KACjC,GAAG,SAAS,CAAC;IACd,MAAM,CAAC,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KACjC,GAAG,SAAS,CAAC;IACd,KAAK,EAAE;QACH,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KACjC,CAAC;IACF,MAAM,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,cAAc,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAChC,GAAG,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,SAAU,SAAQ,gBAAgB;CAAG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-config.js","sourceRoot":"","sources":["../../src/config/app-config.ts"],"names":[],"mappings":"","sourcesContent":["/* Auto-generated. Do not edit by hand. */\nexport interface ProjectAppConfig {\n uns: {\n graphql: string;\n rest: string;\n instanceMode?: \"wait\" | \"force\" | \"handover\";\n processName?: string | undefined;\n handover?: boolean;\n jwksWellKnownUrl?: string | undefined;\n kidWellKnownUrl?: string | undefined;\n env?: \"dev\" | \"staging\" | \"test\" | \"prod\";\n };\n input?: {\n host: string;\n username?: string | undefined;\n password?: string | undefined;\n clientId?: string | undefined;\n } | undefined;\n output?: {\n host: string;\n username?: string | undefined;\n password?: string | undefined;\n clientId?: string | undefined;\n } | undefined;\n infra: {\n host: string;\n username?: string | undefined;\n password?: string | undefined;\n clientId?: string | undefined;\n };\n devops?: {\n provider?: \"azure-devops\";\n organization: string;\n project?: string | undefined;\n } | undefined;\n}\n\nexport interface AppConfig extends ProjectAppConfig {}
|
|
1
|
+
{"version":3,"file":"app-config.js","sourceRoot":"","sources":["../../src/config/app-config.ts"],"names":[],"mappings":"","sourcesContent":["/* Auto-generated. Do not edit by hand. */\nexport interface ProjectAppConfig {\n uns: {\n graphql: string;\n rest: string;\n /** Email used when authenticating to graphql endpoint of the UNS instance. */\n email: string;\n /** Password or secret value paired with the UNS email. */\n password: string | ({\n /** Load the secret from an environment variable. */\n provider: \"env\";\n /** Name of the environment variable to read. */\n key: string;\n /** Allow the variable to be absent without throwing during resolution. */\n optional?: boolean | undefined;\n /** Fallback value when optional is true and the variable is missing. */\n default?: string | undefined;\n } | {\n /** Load the secret from Infisical. */\n provider: \"infisical\";\n /** Secret folder path in Infisical, e.g. '/app/database'. */\n path: string;\n /** Secret key/name inside the given path. */\n key: string;\n /** Allow the secret to be absent without throwing during resolution. */\n optional?: boolean | undefined;\n /** Infisical environment override (defaults to current mode if omitted). */\n environment?: string | undefined;\n /** Optional Infisical project identifier when not using the default. */\n projectId?: string | undefined;\n /** Fallback value when the secret is missing and optional resolution is allowed. */\n default?: string | undefined;\n });\n instanceMode?: \"wait\" | \"force\" | \"handover\";\n processName?: string | undefined;\n handover?: boolean;\n jwksWellKnownUrl?: string | undefined;\n kidWellKnownUrl?: string | undefined;\n env?: \"dev\" | \"staging\" | \"test\" | \"prod\";\n };\n input?: {\n host: string;\n username?: string | undefined;\n password?: string | undefined;\n clientId?: string | undefined;\n } | undefined;\n output?: {\n host: string;\n username?: string | undefined;\n password?: string | undefined;\n clientId?: string | undefined;\n } | undefined;\n infra: {\n host: string;\n username?: string | undefined;\n password?: string | undefined;\n clientId?: string | undefined;\n };\n devops?: {\n provider?: \"azure-devops\";\n organization: string;\n project?: string | undefined;\n } | undefined;\n}\n\nexport interface AppConfig extends ProjectAppConfig {}"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-client.d.ts","sourceRoot":"","sources":["../../../src/tools/auth/auth-client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth-client.d.ts","sourceRoot":"","sources":["../../../src/tools/auth/auth-client.ts"],"names":[],"mappings":"AAWA;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,KAAK,CAAgB;IAE7B,OAAO;WAMM,MAAM,IAAI,OAAO,CAAC,UAAU,CAAC;IAQpC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAuCvC,OAAO,CAAC,MAAM,CAAC,SAAS;IAWxB,OAAO,CAAC,MAAM,CAAC,QAAQ;mBAOF,gBAAgB;IAWrC,OAAO,CAAC,MAAM,CAAC,oBAAoB;YAWrB,KAAK;YAmBL,OAAO;YAmBP,aAAa;WAKd,iBAAiB,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CA0C/E"}
|
|
@@ -2,6 +2,7 @@ import { ConfigFile } from "../../config-file.js";
|
|
|
2
2
|
import { SecureStoreFactory } from "./secure-store.js";
|
|
3
3
|
import jwt from "jsonwebtoken";
|
|
4
4
|
import readline from "readline";
|
|
5
|
+
const cfg = await ConfigFile.loadConfig();
|
|
5
6
|
/**
|
|
6
7
|
* AuthClient handles acquiring and refreshing JWT access tokens
|
|
7
8
|
* using the configured REST base URL.
|
|
@@ -16,7 +17,6 @@ export class AuthClient {
|
|
|
16
17
|
this.namespace = `uns-auth:${this.restBase}`;
|
|
17
18
|
}
|
|
18
19
|
static async create() {
|
|
19
|
-
const cfg = await ConfigFile.loadConfig();
|
|
20
20
|
const restBase = cfg?.uns?.rest;
|
|
21
21
|
if (!restBase)
|
|
22
22
|
throw new Error("config.uns.rest is not set");
|
|
@@ -41,6 +41,19 @@ export class AuthClient {
|
|
|
41
41
|
// ignore, fallback to login
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
+
// First try to get email and password from config
|
|
45
|
+
const configEmail = cfg?.uns?.email;
|
|
46
|
+
const configPassword = cfg?.uns?.password;
|
|
47
|
+
if (typeof configEmail === "string" && typeof configPassword === "string") {
|
|
48
|
+
try {
|
|
49
|
+
const loggedIn = await this.login(configEmail, configPassword);
|
|
50
|
+
await this.persistTokens(loggedIn.accessToken, loggedIn.refreshToken);
|
|
51
|
+
return loggedIn.accessToken;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// ignore, fallback to interactive login
|
|
55
|
+
}
|
|
56
|
+
}
|
|
44
57
|
// Interactive login
|
|
45
58
|
const { email, password } = await AuthClient.promptCredentials();
|
|
46
59
|
const loggedIn = await this.login(email, password);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-client.js","sourceRoot":"","sources":["../../../src/tools/auth/auth-client.ts"],"names":[],"mappings":"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","sourcesContent":["import { ConfigFile } from \"../../config-file.js\";\nimport { SecureStoreFactory, ISecureStore } from \"./secure-store.js\";\nimport jwt from \"jsonwebtoken\";\nimport readline from \"readline\";\n\ntype LoginResponse = {\n accessToken: string;\n};\n\n/**\n * AuthClient handles acquiring and refreshing JWT access tokens\n * using the configured REST base URL.\n */\nexport class AuthClient {\n private readonly restBase: string;\n private readonly namespace: string;\n private store!: ISecureStore;\n\n private constructor(restBase: string) {\n this.restBase = restBase.replace(/\\/$/, \"\");\n // namespace store by rest base to allow multiple environments\n this.namespace = `uns-auth:${this.restBase}`;\n }\n\n static async create(): Promise<AuthClient> {\n const cfg = await ConfigFile.loadConfig();\n const restBase: string = cfg?.uns?.rest;\n if (!restBase) throw new Error(\"config.uns.rest is not set\");\n const client = new AuthClient(restBase);\n client.store = await SecureStoreFactory.create(client.namespace);\n return client;\n }\n\n async getAccessToken(): Promise<string> {\n const accessToken = await this.store.get(\"accessToken\");\n const refreshToken = await this.store.get(\"refreshToken\");\n\n if (accessToken && !AuthClient.isExpired(accessToken)) {\n return accessToken;\n }\n\n // Try refresh if we have refresh token\n if (refreshToken) {\n try {\n const refreshed = await this.refresh(refreshToken);\n await this.persistTokens(refreshed.accessToken, refreshed.refreshToken);\n return refreshed.accessToken;\n } catch {\n // ignore, fallback to login\n }\n }\n\n // Interactive login\n const { email, password } = await AuthClient.promptCredentials();\n const loggedIn = await this.login(email, password);\n await this.persistTokens(loggedIn.accessToken, loggedIn.refreshToken);\n return loggedIn.accessToken;\n }\n\n private static isExpired(token: string, skewSeconds = 30): boolean {\n try {\n const decoded: any = jwt.decode(token);\n if (!decoded || typeof decoded !== \"object\" || !decoded.exp) return true;\n const now = Math.floor(Date.now() / 1000);\n return decoded.exp <= now + skewSeconds;\n } catch {\n return true;\n }\n }\n\n private static endpoint(base: string, tail: string): string {\n // base ends without trailing slash; tail must not start with slash\n const b = base.replace(/\\/$/, \"\");\n const t = tail.replace(/^\\//, \"\");\n return `${b}/${t}`;\n }\n\n private static async fetchWithTimeout(url: string, init: RequestInit = {}, timeoutMs = 10_000): Promise<Response> {\n const controller = new AbortController();\n const id = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const resp = await fetch(url, { ...init, signal: controller.signal });\n return resp;\n } finally {\n clearTimeout(id);\n }\n }\n\n private static extractRefreshCookie(resp: Response): string | null {\n const anyHeaders: any = resp.headers as any;\n const getSetCookie = typeof anyHeaders.getSetCookie === \"function\" ? anyHeaders.getSetCookie.bind(anyHeaders) : null;\n const candidates: string[] = getSetCookie ? getSetCookie() : (resp.headers.get(\"set-cookie\") ? [resp.headers.get(\"set-cookie\") as string] : []);\n for (const header of candidates) {\n const match = header.match(/(?:^|;\\s*)RefreshToken=([^;]+)/i);\n if (match) return match[1];\n }\n return null;\n }\n\n private async login(email: string, password: string): Promise<{ accessToken: string; refreshToken: string; }> {\n const url = AuthClient.endpoint(this.restBase, \"auth/login\");\n const resp = await AuthClient.fetchWithTimeout(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email, password }),\n }, 12_000);\n\n if (!resp.ok) {\n throw new Error(`Login failed: ${resp.status} ${resp.statusText}`);\n }\n const data = (await resp.json()) as LoginResponse;\n const refreshToken = AuthClient.extractRefreshCookie(resp);\n if (!data?.accessToken || !refreshToken) {\n throw new Error(\"Login response missing tokens\");\n }\n return { accessToken: data.accessToken, refreshToken };\n }\n\n private async refresh(refreshToken: string): Promise<{ accessToken: string; refreshToken: string; }> {\n const url = AuthClient.endpoint(this.restBase, \"auth/refresh\");\n const resp = await AuthClient.fetchWithTimeout(url, {\n method: \"POST\",\n headers: {\n // server expects cookie RefreshToken\n \"Cookie\": `RefreshToken=${refreshToken}`,\n },\n }, 8_000);\n\n if (!resp.ok) {\n throw new Error(`Refresh failed: ${resp.status} ${resp.statusText}`);\n }\n const data = (await resp.json()) as LoginResponse;\n const newRefreshToken = AuthClient.extractRefreshCookie(resp) || refreshToken;\n if (!data?.accessToken) throw new Error(\"Refresh response missing accessToken\");\n return { accessToken: data.accessToken, refreshToken: newRefreshToken };\n }\n\n private async persistTokens(accessToken: string, refreshToken: string): Promise<void> {\n await this.store.set(\"accessToken\", accessToken);\n await this.store.set(\"refreshToken\", refreshToken);\n }\n\n static async promptCredentials(): Promise<{ email: string; password: string }> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true });\n\n const ask = (q: string) => new Promise<string>((resolve) => rl.question(q, (ans) => resolve(ans.trim())));\n\n const askMasked = (q: string) => new Promise<string>((resolve) => {\n const anyRl = rl as any;\n const out: any = anyRl.output || process.stdout;\n const origWrite = (anyRl._writeToOutput as ((str: string) => void))?.bind(rl) || ((s: string) => out.write(s));\n anyRl.stdoutMuted = true;\n anyRl._writeToOutput = function (stringToWrite: string) {\n // Keep prompt text intact; mask user input\n if (anyRl.stdoutMuted) {\n if (stringToWrite.startsWith(q)) {\n out.write(stringToWrite);\n } else if (stringToWrite.endsWith(\"\\n\")) {\n out.write(\"\\n\");\n } else {\n out.write(\"*\");\n }\n } else {\n origWrite(stringToWrite);\n }\n };\n rl.question(q, (value) => {\n anyRl.stdoutMuted = false;\n anyRl._writeToOutput = origWrite;\n out.write(\"\\n\");\n resolve(value.trim());\n });\n });\n\n try {\n const email = await ask(\"Email: \");\n const password = await askMasked(\"Password: \");\n rl.close();\n return { email, password };\n } catch (e) {\n rl.close();\n throw e;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"auth-client.js","sourceRoot":"","sources":["../../../src/tools/auth/auth-client.ts"],"names":[],"mappings":"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","sourcesContent":["import { ConfigFile } from \"../../config-file.js\";\nimport { SecureStoreFactory, ISecureStore } from \"./secure-store.js\";\nimport jwt from \"jsonwebtoken\";\nimport readline from \"readline\";\n\nconst cfg = await ConfigFile.loadConfig();\n\ntype LoginResponse = {\n accessToken: string;\n};\n\n/**\n * AuthClient handles acquiring and refreshing JWT access tokens\n * using the configured REST base URL.\n */\nexport class AuthClient {\n private readonly restBase: string;\n private readonly namespace: string;\n private store!: ISecureStore;\n\n private constructor(restBase: string) {\n this.restBase = restBase.replace(/\\/$/, \"\");\n // namespace store by rest base to allow multiple environments\n this.namespace = `uns-auth:${this.restBase}`;\n }\n\n static async create(): Promise<AuthClient> {\n const restBase: string = cfg?.uns?.rest;\n if (!restBase) throw new Error(\"config.uns.rest is not set\");\n const client = new AuthClient(restBase);\n client.store = await SecureStoreFactory.create(client.namespace);\n return client;\n }\n\n async getAccessToken(): Promise<string> {\n const accessToken = await this.store.get(\"accessToken\");\n const refreshToken = await this.store.get(\"refreshToken\");\n\n if (accessToken && !AuthClient.isExpired(accessToken)) {\n return accessToken;\n }\n\n // Try refresh if we have refresh token\n if (refreshToken) {\n try {\n const refreshed = await this.refresh(refreshToken);\n await this.persistTokens(refreshed.accessToken, refreshed.refreshToken);\n return refreshed.accessToken;\n } catch {\n // ignore, fallback to login\n }\n }\n\n // First try to get email and password from config\n const configEmail = cfg?.uns?.email;\n const configPassword = cfg?.uns?.password;\n if (typeof configEmail === \"string\" && typeof configPassword === \"string\") {\n try {\n const loggedIn = await this.login(configEmail, configPassword);\n await this.persistTokens(loggedIn.accessToken, loggedIn.refreshToken);\n return loggedIn.accessToken;\n } catch {\n // ignore, fallback to interactive login\n }\n }\n\n // Interactive login\n const { email, password } = await AuthClient.promptCredentials();\n const loggedIn = await this.login(email, password);\n await this.persistTokens(loggedIn.accessToken, loggedIn.refreshToken);\n return loggedIn.accessToken;\n }\n\n private static isExpired(token: string, skewSeconds = 30): boolean {\n try {\n const decoded: any = jwt.decode(token);\n if (!decoded || typeof decoded !== \"object\" || !decoded.exp) return true;\n const now = Math.floor(Date.now() / 1000);\n return decoded.exp <= now + skewSeconds;\n } catch {\n return true;\n }\n }\n\n private static endpoint(base: string, tail: string): string {\n // base ends without trailing slash; tail must not start with slash\n const b = base.replace(/\\/$/, \"\");\n const t = tail.replace(/^\\//, \"\");\n return `${b}/${t}`;\n }\n\n private static async fetchWithTimeout(url: string, init: RequestInit = {}, timeoutMs = 10_000): Promise<Response> {\n const controller = new AbortController();\n const id = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const resp = await fetch(url, { ...init, signal: controller.signal });\n return resp;\n } finally {\n clearTimeout(id);\n }\n }\n\n private static extractRefreshCookie(resp: Response): string | null {\n const anyHeaders: any = resp.headers as any;\n const getSetCookie = typeof anyHeaders.getSetCookie === \"function\" ? anyHeaders.getSetCookie.bind(anyHeaders) : null;\n const candidates: string[] = getSetCookie ? getSetCookie() : (resp.headers.get(\"set-cookie\") ? [resp.headers.get(\"set-cookie\") as string] : []);\n for (const header of candidates) {\n const match = header.match(/(?:^|;\\s*)RefreshToken=([^;]+)/i);\n if (match) return match[1];\n }\n return null;\n }\n\n private async login(email: string, password: string): Promise<{ accessToken: string; refreshToken: string; }> {\n const url = AuthClient.endpoint(this.restBase, \"auth/login\");\n const resp = await AuthClient.fetchWithTimeout(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email, password }),\n }, 12_000);\n\n if (!resp.ok) {\n throw new Error(`Login failed: ${resp.status} ${resp.statusText}`);\n }\n const data = (await resp.json()) as LoginResponse;\n const refreshToken = AuthClient.extractRefreshCookie(resp);\n if (!data?.accessToken || !refreshToken) {\n throw new Error(\"Login response missing tokens\");\n }\n return { accessToken: data.accessToken, refreshToken };\n }\n\n private async refresh(refreshToken: string): Promise<{ accessToken: string; refreshToken: string; }> {\n const url = AuthClient.endpoint(this.restBase, \"auth/refresh\");\n const resp = await AuthClient.fetchWithTimeout(url, {\n method: \"POST\",\n headers: {\n // server expects cookie RefreshToken\n \"Cookie\": `RefreshToken=${refreshToken}`,\n },\n }, 8_000);\n\n if (!resp.ok) {\n throw new Error(`Refresh failed: ${resp.status} ${resp.statusText}`);\n }\n const data = (await resp.json()) as LoginResponse;\n const newRefreshToken = AuthClient.extractRefreshCookie(resp) || refreshToken;\n if (!data?.accessToken) throw new Error(\"Refresh response missing accessToken\");\n return { accessToken: data.accessToken, refreshToken: newRefreshToken };\n }\n\n private async persistTokens(accessToken: string, refreshToken: string): Promise<void> {\n await this.store.set(\"accessToken\", accessToken);\n await this.store.set(\"refreshToken\", refreshToken);\n }\n\n static async promptCredentials(): Promise<{ email: string; password: string }> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true });\n\n const ask = (q: string) => new Promise<string>((resolve) => rl.question(q, (ans) => resolve(ans.trim())));\n\n const askMasked = (q: string) => new Promise<string>((resolve) => {\n const anyRl = rl as any;\n const out: any = anyRl.output || process.stdout;\n const origWrite = (anyRl._writeToOutput as ((str: string) => void))?.bind(rl) || ((s: string) => out.write(s));\n anyRl.stdoutMuted = true;\n anyRl._writeToOutput = function (stringToWrite: string) {\n // Keep prompt text intact; mask user input\n if (anyRl.stdoutMuted) {\n if (stringToWrite.startsWith(q)) {\n out.write(stringToWrite);\n } else if (stringToWrite.endsWith(\"\\n\")) {\n out.write(\"\\n\");\n } else {\n out.write(\"*\");\n }\n } else {\n origWrite(stringToWrite);\n }\n };\n rl.question(q, (value) => {\n anyRl.stdoutMuted = false;\n anyRl._writeToOutput = origWrite;\n out.write(\"\\n\");\n resolve(value.trim());\n });\n });\n\n try {\n const email = await ask(\"Email: \");\n const password = await askMasked(\"Password: \");\n rl.close();\n return { email, password };\n } catch (e) {\n rl.close();\n throw e;\n }\n }\n}\n"]}
|
|
@@ -51,8 +51,8 @@ export declare const unsCoreSchema: z.ZodObject<{
|
|
|
51
51
|
kidWellKnownUrl: z.ZodOptional<z.ZodString>;
|
|
52
52
|
env: z.ZodDefault<z.ZodEnum<["dev", "staging", "test", "prod"]>>;
|
|
53
53
|
}, "strict", z.ZodTypeAny, {
|
|
54
|
-
handover?: boolean;
|
|
55
54
|
env?: "dev" | "staging" | "test" | "prod";
|
|
55
|
+
handover?: boolean;
|
|
56
56
|
processName?: string;
|
|
57
57
|
password?: string | {
|
|
58
58
|
provider?: "env";
|
|
@@ -75,8 +75,8 @@ export declare const unsCoreSchema: z.ZodObject<{
|
|
|
75
75
|
jwksWellKnownUrl?: string;
|
|
76
76
|
kidWellKnownUrl?: string;
|
|
77
77
|
}, {
|
|
78
|
-
handover?: boolean;
|
|
79
78
|
env?: "dev" | "staging" | "test" | "prod";
|
|
79
|
+
handover?: boolean;
|
|
80
80
|
processName?: string;
|
|
81
81
|
password?: string | {
|
|
82
82
|
provider?: "env";
|
|
@@ -567,8 +567,8 @@ export declare const unsCoreSchema: z.ZodObject<{
|
|
|
567
567
|
}>>;
|
|
568
568
|
}, "strict", z.ZodTypeAny, {
|
|
569
569
|
uns?: {
|
|
570
|
-
handover?: boolean;
|
|
571
570
|
env?: "dev" | "staging" | "test" | "prod";
|
|
571
|
+
handover?: boolean;
|
|
572
572
|
processName?: string;
|
|
573
573
|
password?: string | {
|
|
574
574
|
provider?: "env";
|
|
@@ -697,8 +697,8 @@ export declare const unsCoreSchema: z.ZodObject<{
|
|
|
697
697
|
};
|
|
698
698
|
}, {
|
|
699
699
|
uns?: {
|
|
700
|
-
handover?: boolean;
|
|
701
700
|
env?: "dev" | "staging" | "test" | "prod";
|
|
701
|
+
handover?: boolean;
|
|
702
702
|
processName?: string;
|
|
703
703
|
password?: string | {
|
|
704
704
|
provider?: "env";
|