saasignal 0.9.13 → 0.9.15
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/auth.d.ts +79 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +365 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli.js +111 -34
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +75 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +130 -20
- package/dist/client.js.map +1 -1
- package/dist/types.d.ts +98 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
interface ProtectedResourceMetadata {
|
|
2
|
+
resource?: string;
|
|
3
|
+
authorization_servers?: string[];
|
|
4
|
+
}
|
|
5
|
+
interface AuthorizationServerMetadata {
|
|
6
|
+
issuer: string;
|
|
7
|
+
authorization_endpoint: string;
|
|
8
|
+
token_endpoint: string;
|
|
9
|
+
registration_endpoint?: string;
|
|
10
|
+
revocation_endpoint?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface StoredAuthProfile {
|
|
13
|
+
access_token: string;
|
|
14
|
+
refresh_token: string;
|
|
15
|
+
expires_at: string;
|
|
16
|
+
client_id: string;
|
|
17
|
+
issuer: string;
|
|
18
|
+
authorization_endpoint: string;
|
|
19
|
+
token_endpoint: string;
|
|
20
|
+
registration_endpoint?: string;
|
|
21
|
+
revocation_endpoint?: string;
|
|
22
|
+
resource: string;
|
|
23
|
+
base_url: string;
|
|
24
|
+
org_id: string | null;
|
|
25
|
+
project_id: string | null;
|
|
26
|
+
scopes: string[];
|
|
27
|
+
}
|
|
28
|
+
export interface ResolvedCliAuth {
|
|
29
|
+
token: string;
|
|
30
|
+
baseUrl: string;
|
|
31
|
+
source: "env_token" | "stored_oauth" | "env_api_key";
|
|
32
|
+
profile?: StoredAuthProfile;
|
|
33
|
+
}
|
|
34
|
+
type FetchLike = typeof fetch;
|
|
35
|
+
export declare function getAuthConfigPath(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv, home?: string): string;
|
|
36
|
+
export declare function loadAuthProfile(path?: string): Promise<StoredAuthProfile | null>;
|
|
37
|
+
export declare function saveAuthProfile(profile: StoredAuthProfile, path?: string): Promise<void>;
|
|
38
|
+
export declare function deleteAuthProfile(path?: string): Promise<void>;
|
|
39
|
+
export declare function createPkcePair(): {
|
|
40
|
+
codeVerifier: string;
|
|
41
|
+
codeChallenge: string;
|
|
42
|
+
};
|
|
43
|
+
export declare function discoverOAuthConfiguration(baseUrl: string, fetchImpl?: FetchLike): Promise<{
|
|
44
|
+
baseUrl: string;
|
|
45
|
+
protectedResource: ProtectedResourceMetadata;
|
|
46
|
+
metadata: AuthorizationServerMetadata;
|
|
47
|
+
}>;
|
|
48
|
+
export declare function authorizeWithBrowser(options?: {
|
|
49
|
+
baseUrl?: string;
|
|
50
|
+
fetchImpl?: FetchLike;
|
|
51
|
+
onAuthorizeUrl?: (url: string) => void;
|
|
52
|
+
openBrowser?: (url: string) => void | Promise<void>;
|
|
53
|
+
timeoutMs?: number;
|
|
54
|
+
}): Promise<StoredAuthProfile>;
|
|
55
|
+
export declare function refreshAuthProfile(profile: StoredAuthProfile, fetchImpl?: FetchLike): Promise<StoredAuthProfile>;
|
|
56
|
+
export declare function shouldRefreshProfile(profile: StoredAuthProfile, now?: number): boolean;
|
|
57
|
+
export declare function resolveCliAuth(options?: {
|
|
58
|
+
baseUrl?: string;
|
|
59
|
+
fetchImpl?: FetchLike;
|
|
60
|
+
profilePath?: string;
|
|
61
|
+
}): Promise<{
|
|
62
|
+
token: string;
|
|
63
|
+
baseUrl: string;
|
|
64
|
+
source: "env_token";
|
|
65
|
+
profile?: undefined;
|
|
66
|
+
} | {
|
|
67
|
+
token: string;
|
|
68
|
+
baseUrl: string;
|
|
69
|
+
source: "stored_oauth";
|
|
70
|
+
profile: StoredAuthProfile;
|
|
71
|
+
} | {
|
|
72
|
+
token: string;
|
|
73
|
+
baseUrl: string;
|
|
74
|
+
source: "env_api_key";
|
|
75
|
+
profile?: undefined;
|
|
76
|
+
}>;
|
|
77
|
+
export declare function revokeAndDeleteAuthProfile(profile: StoredAuthProfile | null, fetchImpl?: FetchLike, path?: string): Promise<void>;
|
|
78
|
+
export {};
|
|
79
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAWA,UAAU,yBAAyB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAA;CACjC;AAED,UAAU,2BAA2B;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,sBAAsB,EAAE,MAAM,CAAA;IAC9B,cAAc,EAAE,MAAM,CAAA;IACtB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAiBD,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,sBAAsB,EAAE,MAAM,CAAA;IAC9B,cAAc,EAAE,MAAM,CAAA;IACtB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,WAAW,GAAG,cAAc,GAAG,aAAa,CAAA;IACpD,OAAO,CAAC,EAAE,iBAAiB,CAAA;CAC5B;AAED,KAAK,SAAS,GAAG,OAAO,KAAK,CAAA;AA4D7B,wBAAgB,iBAAiB,CAC/B,QAAQ,kBAAmB,EAC3B,GAAG,oBAAc,EACjB,IAAI,SAAY,UASjB;AAED,wBAAsB,eAAe,CAAC,IAAI,SAAsB,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAgCnG;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,iBAAiB,EAAE,IAAI,SAAsB,iBAQ3F;AAED,wBAAsB,iBAAiB,CAAC,IAAI,SAAsB,iBAEjE;AAED,wBAAgB,cAAc;;;EAI7B;AAED,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,GAAE,SAAiB;;;;GAiC7F;AAsID,wBAAsB,oBAAoB,CAAC,OAAO,CAAC,EAAE;IACnD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACnD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,8BA4CA;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,EAAE,SAAS,GAAE,SAAiB,8BAmBhG;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,SAAa,WAEhF;AAED,wBAAsB,cAAc,CAAC,OAAO,CAAC,EAAE;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;;;;;;;;;;;;;;;GAuCA;AAED,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,EAAE,SAAS,GAAE,SAAiB,EAAE,IAAI,SAAsB,iBAY3I"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
3
|
+
import { chmod, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { createServer } from "node:http";
|
|
5
|
+
import { homedir } from "node:os";
|
|
6
|
+
import { dirname, join } from "node:path";
|
|
7
|
+
const DEFAULT_BASE_URL = "https://api.saasignal.saastemly.com";
|
|
8
|
+
const CALLBACK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
9
|
+
const REFRESH_SKEW_MS = 60 * 1000;
|
|
10
|
+
function normalizeBaseUrl(value) {
|
|
11
|
+
return (value ?? process.env.SAASIGNAL_API_URL ?? DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
12
|
+
}
|
|
13
|
+
function parseScope(scope) {
|
|
14
|
+
return (scope ?? "").split(/\s+/).filter(Boolean);
|
|
15
|
+
}
|
|
16
|
+
function profileFromTokenResponse(response, metadata, baseUrl, clientId) {
|
|
17
|
+
return {
|
|
18
|
+
access_token: response.access_token,
|
|
19
|
+
refresh_token: response.refresh_token,
|
|
20
|
+
expires_at: new Date(Date.now() + response.expires_in * 1000).toISOString(),
|
|
21
|
+
client_id: clientId,
|
|
22
|
+
issuer: metadata.issuer,
|
|
23
|
+
authorization_endpoint: metadata.authorization_endpoint,
|
|
24
|
+
token_endpoint: metadata.token_endpoint,
|
|
25
|
+
registration_endpoint: metadata.registration_endpoint,
|
|
26
|
+
revocation_endpoint: metadata.revocation_endpoint,
|
|
27
|
+
resource: response.resource ?? baseUrl,
|
|
28
|
+
base_url: baseUrl,
|
|
29
|
+
org_id: response.org_id ?? null,
|
|
30
|
+
project_id: response.project_id ?? null,
|
|
31
|
+
scopes: parseScope(response.scope),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async function readJsonFile(path) {
|
|
35
|
+
const raw = await readFile(path, "utf8");
|
|
36
|
+
return JSON.parse(raw);
|
|
37
|
+
}
|
|
38
|
+
async function postForm(fetchImpl, url, body) {
|
|
39
|
+
const response = await fetchImpl(url, {
|
|
40
|
+
method: "POST",
|
|
41
|
+
headers: {
|
|
42
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
43
|
+
Accept: "application/json",
|
|
44
|
+
},
|
|
45
|
+
body,
|
|
46
|
+
});
|
|
47
|
+
const json = await response.json().catch(() => null);
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
const message = typeof json === "object" && json && "error_description" in json
|
|
50
|
+
? String(json.error_description)
|
|
51
|
+
: `HTTP ${response.status}`;
|
|
52
|
+
throw new Error(message);
|
|
53
|
+
}
|
|
54
|
+
return json;
|
|
55
|
+
}
|
|
56
|
+
export function getAuthConfigPath(platform = process.platform, env = process.env, home = homedir()) {
|
|
57
|
+
if (platform === "win32") {
|
|
58
|
+
return join(env.APPDATA ?? join(home, "AppData", "Roaming"), "saasignal", "auth.json");
|
|
59
|
+
}
|
|
60
|
+
if (platform === "darwin") {
|
|
61
|
+
return join(home, "Library", "Application Support", "saasignal", "auth.json");
|
|
62
|
+
}
|
|
63
|
+
return join(env.XDG_CONFIG_HOME ?? join(home, ".config"), "saasignal", "auth.json");
|
|
64
|
+
}
|
|
65
|
+
export async function loadAuthProfile(path = getAuthConfigPath()) {
|
|
66
|
+
try {
|
|
67
|
+
const json = await readJsonFile(path);
|
|
68
|
+
if (typeof json.access_token !== "string" ||
|
|
69
|
+
typeof json.refresh_token !== "string" ||
|
|
70
|
+
typeof json.client_id !== "string" ||
|
|
71
|
+
typeof json.token_endpoint !== "string" ||
|
|
72
|
+
typeof json.resource !== "string") {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
access_token: json.access_token,
|
|
77
|
+
refresh_token: json.refresh_token,
|
|
78
|
+
expires_at: typeof json.expires_at === "string" ? json.expires_at : new Date(0).toISOString(),
|
|
79
|
+
client_id: json.client_id,
|
|
80
|
+
issuer: typeof json.issuer === "string" ? json.issuer : "",
|
|
81
|
+
authorization_endpoint: typeof json.authorization_endpoint === "string" ? json.authorization_endpoint : "",
|
|
82
|
+
token_endpoint: json.token_endpoint,
|
|
83
|
+
registration_endpoint: typeof json.registration_endpoint === "string" ? json.registration_endpoint : undefined,
|
|
84
|
+
revocation_endpoint: typeof json.revocation_endpoint === "string" ? json.revocation_endpoint : undefined,
|
|
85
|
+
resource: json.resource,
|
|
86
|
+
base_url: typeof json.base_url === "string" ? json.base_url : normalizeBaseUrl(json.resource),
|
|
87
|
+
org_id: typeof json.org_id === "string" ? json.org_id : null,
|
|
88
|
+
project_id: typeof json.project_id === "string" ? json.project_id : null,
|
|
89
|
+
scopes: Array.isArray(json.scopes) ? json.scopes.filter((scope) => typeof scope === "string") : [],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export async function saveAuthProfile(profile, path = getAuthConfigPath()) {
|
|
97
|
+
const dir = dirname(path);
|
|
98
|
+
await mkdir(dir, { recursive: true, mode: 0o700 });
|
|
99
|
+
await writeFile(path, JSON.stringify(profile, null, 2), { mode: 0o600 });
|
|
100
|
+
if (process.platform !== "win32") {
|
|
101
|
+
await chmod(dir, 0o700).catch(() => { });
|
|
102
|
+
await chmod(path, 0o600).catch(() => { });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export async function deleteAuthProfile(path = getAuthConfigPath()) {
|
|
106
|
+
await rm(path, { force: true });
|
|
107
|
+
}
|
|
108
|
+
export function createPkcePair() {
|
|
109
|
+
const codeVerifier = randomBytes(48).toString("base64url");
|
|
110
|
+
const codeChallenge = createHash("sha256").update(codeVerifier).digest("base64url");
|
|
111
|
+
return { codeVerifier, codeChallenge };
|
|
112
|
+
}
|
|
113
|
+
export async function discoverOAuthConfiguration(baseUrl, fetchImpl = fetch) {
|
|
114
|
+
const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
|
|
115
|
+
const protectedResource = await fetchImpl(`${normalizedBaseUrl}/.well-known/oauth-protected-resource`, {
|
|
116
|
+
headers: { Accept: "application/json" },
|
|
117
|
+
}).then(async (response) => {
|
|
118
|
+
const json = await response.json().catch(() => null);
|
|
119
|
+
if (!response.ok || !json) {
|
|
120
|
+
throw new Error("Unable to discover SaaSignal protected-resource metadata");
|
|
121
|
+
}
|
|
122
|
+
return json;
|
|
123
|
+
});
|
|
124
|
+
const authorizationServer = protectedResource.authorization_servers?.[0];
|
|
125
|
+
if (!authorizationServer) {
|
|
126
|
+
throw new Error("Protected-resource metadata did not advertise an authorization server");
|
|
127
|
+
}
|
|
128
|
+
const metadataUrl = `${authorizationServer.replace(/\/$/, "")}/.well-known/oauth-authorization-server`;
|
|
129
|
+
const metadata = await fetchImpl(metadataUrl, {
|
|
130
|
+
headers: { Accept: "application/json" },
|
|
131
|
+
}).then(async (response) => {
|
|
132
|
+
const json = await response.json().catch(() => null);
|
|
133
|
+
if (!response.ok || !json) {
|
|
134
|
+
throw new Error("Unable to discover SaaSignal authorization-server metadata");
|
|
135
|
+
}
|
|
136
|
+
return json;
|
|
137
|
+
});
|
|
138
|
+
return {
|
|
139
|
+
baseUrl: normalizedBaseUrl,
|
|
140
|
+
protectedResource,
|
|
141
|
+
metadata,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
async function registerDynamicClient(metadata, redirectUri, fetchImpl) {
|
|
145
|
+
if (!metadata.registration_endpoint) {
|
|
146
|
+
throw new Error("Authorization server does not support dynamic client registration");
|
|
147
|
+
}
|
|
148
|
+
const response = await fetchImpl(metadata.registration_endpoint, {
|
|
149
|
+
method: "POST",
|
|
150
|
+
headers: {
|
|
151
|
+
"Content-Type": "application/json",
|
|
152
|
+
Accept: "application/json",
|
|
153
|
+
},
|
|
154
|
+
body: JSON.stringify({
|
|
155
|
+
redirect_uris: [redirectUri],
|
|
156
|
+
token_endpoint_auth_method: "none",
|
|
157
|
+
grant_types: ["authorization_code", "refresh_token"],
|
|
158
|
+
response_types: ["code"],
|
|
159
|
+
client_name: "SaaSignal CLI",
|
|
160
|
+
}),
|
|
161
|
+
});
|
|
162
|
+
const json = await response.json().catch(() => null);
|
|
163
|
+
if (!response.ok || !json || typeof json.client_id !== "string") {
|
|
164
|
+
throw new Error("Unable to register the SaaSignal CLI with the authorization server");
|
|
165
|
+
}
|
|
166
|
+
return json;
|
|
167
|
+
}
|
|
168
|
+
function openSystemBrowser(url) {
|
|
169
|
+
return new Promise((resolve, reject) => {
|
|
170
|
+
const platform = process.platform;
|
|
171
|
+
const child = platform === "darwin"
|
|
172
|
+
? spawn("open", [url], { stdio: "ignore" })
|
|
173
|
+
: platform === "win32"
|
|
174
|
+
? spawn("cmd", ["/c", "start", "", url], { stdio: "ignore", windowsHide: true })
|
|
175
|
+
: spawn("xdg-open", [url], { stdio: "ignore" });
|
|
176
|
+
child.once("error", reject);
|
|
177
|
+
child.once("spawn", () => {
|
|
178
|
+
child.unref();
|
|
179
|
+
resolve();
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
async function createLoopbackListener(expectedState, timeoutMs = CALLBACK_TIMEOUT_MS) {
|
|
184
|
+
let settled = false;
|
|
185
|
+
let rejectPending = () => { };
|
|
186
|
+
let resolvePending = () => { };
|
|
187
|
+
const result = new Promise((resolve, reject) => {
|
|
188
|
+
resolvePending = resolve;
|
|
189
|
+
rejectPending = reject;
|
|
190
|
+
});
|
|
191
|
+
const server = createServer((req, res) => {
|
|
192
|
+
const requestUrl = new URL(req.url ?? "/", `http://${req.headers.host}`);
|
|
193
|
+
if (requestUrl.pathname !== "/callback") {
|
|
194
|
+
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
|
|
195
|
+
res.end("Not found");
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const finish = (callback) => {
|
|
199
|
+
if (settled)
|
|
200
|
+
return;
|
|
201
|
+
settled = true;
|
|
202
|
+
clearTimeout(timer);
|
|
203
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
204
|
+
callback();
|
|
205
|
+
server.close();
|
|
206
|
+
};
|
|
207
|
+
const error = requestUrl.searchParams.get("error");
|
|
208
|
+
if (error) {
|
|
209
|
+
const description = requestUrl.searchParams.get("error_description") ?? error;
|
|
210
|
+
finish(() => {
|
|
211
|
+
res.end(`<p>SaaSignal authorization failed: ${description}</p>`);
|
|
212
|
+
rejectPending(new Error(description));
|
|
213
|
+
});
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const code = requestUrl.searchParams.get("code");
|
|
217
|
+
const state = requestUrl.searchParams.get("state");
|
|
218
|
+
if (!code || state !== expectedState) {
|
|
219
|
+
finish(() => {
|
|
220
|
+
res.end("<p>SaaSignal authorization failed: state mismatch.</p>");
|
|
221
|
+
rejectPending(new Error("OAuth state mismatch"));
|
|
222
|
+
});
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
finish(() => {
|
|
226
|
+
res.end("<p>SaaSignal authorization complete. You can return to the terminal.</p>");
|
|
227
|
+
resolvePending({ code });
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
await new Promise((resolve, reject) => {
|
|
231
|
+
server.once("error", reject);
|
|
232
|
+
server.listen(0, "127.0.0.1", () => resolve());
|
|
233
|
+
});
|
|
234
|
+
const address = server.address();
|
|
235
|
+
if (!address || typeof address === "string") {
|
|
236
|
+
server.close();
|
|
237
|
+
throw new Error("Unable to start the OAuth callback listener");
|
|
238
|
+
}
|
|
239
|
+
const timer = setTimeout(() => {
|
|
240
|
+
if (settled)
|
|
241
|
+
return;
|
|
242
|
+
settled = true;
|
|
243
|
+
server.close();
|
|
244
|
+
rejectPending(new Error("Timed out waiting for the SaaSignal browser authorization callback"));
|
|
245
|
+
}, timeoutMs);
|
|
246
|
+
return {
|
|
247
|
+
redirectUri: `http://127.0.0.1:${address.port}/callback`,
|
|
248
|
+
waitForCode: () => result,
|
|
249
|
+
close: () => {
|
|
250
|
+
if (settled)
|
|
251
|
+
return;
|
|
252
|
+
settled = true;
|
|
253
|
+
clearTimeout(timer);
|
|
254
|
+
server.close();
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
export async function authorizeWithBrowser(options) {
|
|
259
|
+
const fetchImpl = options?.fetchImpl ?? fetch;
|
|
260
|
+
const baseUrl = normalizeBaseUrl(options?.baseUrl);
|
|
261
|
+
const { metadata, protectedResource } = await discoverOAuthConfiguration(baseUrl, fetchImpl);
|
|
262
|
+
const state = randomBytes(24).toString("base64url");
|
|
263
|
+
const { codeVerifier, codeChallenge } = createPkcePair();
|
|
264
|
+
const listener = await createLoopbackListener(state, options?.timeoutMs);
|
|
265
|
+
try {
|
|
266
|
+
const client = await registerDynamicClient(metadata, listener.redirectUri, fetchImpl);
|
|
267
|
+
const authorizeUrl = new URL(metadata.authorization_endpoint);
|
|
268
|
+
authorizeUrl.searchParams.set("client_id", client.client_id);
|
|
269
|
+
authorizeUrl.searchParams.set("redirect_uri", listener.redirectUri);
|
|
270
|
+
authorizeUrl.searchParams.set("response_type", "code");
|
|
271
|
+
authorizeUrl.searchParams.set("code_challenge", codeChallenge);
|
|
272
|
+
authorizeUrl.searchParams.set("code_challenge_method", "S256");
|
|
273
|
+
authorizeUrl.searchParams.set("state", state);
|
|
274
|
+
authorizeUrl.searchParams.set("resource", protectedResource.resource ?? baseUrl);
|
|
275
|
+
options?.onAuthorizeUrl?.(authorizeUrl.toString());
|
|
276
|
+
try {
|
|
277
|
+
await (options?.openBrowser ?? openSystemBrowser)(authorizeUrl.toString());
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
// If opening the browser fails we still keep waiting so the user can open the URL manually.
|
|
281
|
+
}
|
|
282
|
+
const { code } = await listener.waitForCode();
|
|
283
|
+
const tokenResponse = await postForm(fetchImpl, metadata.token_endpoint, new URLSearchParams({
|
|
284
|
+
grant_type: "authorization_code",
|
|
285
|
+
client_id: client.client_id,
|
|
286
|
+
code,
|
|
287
|
+
code_verifier: codeVerifier,
|
|
288
|
+
redirect_uri: listener.redirectUri,
|
|
289
|
+
resource: protectedResource.resource ?? baseUrl,
|
|
290
|
+
}));
|
|
291
|
+
return profileFromTokenResponse(tokenResponse, metadata, baseUrl, client.client_id);
|
|
292
|
+
}
|
|
293
|
+
finally {
|
|
294
|
+
listener.close();
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
export async function refreshAuthProfile(profile, fetchImpl = fetch) {
|
|
298
|
+
const tokenResponse = await postForm(fetchImpl, profile.token_endpoint, new URLSearchParams({
|
|
299
|
+
grant_type: "refresh_token",
|
|
300
|
+
client_id: profile.client_id,
|
|
301
|
+
refresh_token: profile.refresh_token,
|
|
302
|
+
resource: profile.resource,
|
|
303
|
+
}));
|
|
304
|
+
return profileFromTokenResponse(tokenResponse, {
|
|
305
|
+
issuer: profile.issuer,
|
|
306
|
+
authorization_endpoint: profile.authorization_endpoint,
|
|
307
|
+
token_endpoint: profile.token_endpoint,
|
|
308
|
+
registration_endpoint: profile.registration_endpoint,
|
|
309
|
+
revocation_endpoint: profile.revocation_endpoint,
|
|
310
|
+
}, profile.base_url, profile.client_id);
|
|
311
|
+
}
|
|
312
|
+
export function shouldRefreshProfile(profile, now = Date.now()) {
|
|
313
|
+
return new Date(profile.expires_at).getTime() - now <= REFRESH_SKEW_MS;
|
|
314
|
+
}
|
|
315
|
+
export async function resolveCliAuth(options) {
|
|
316
|
+
const baseUrl = normalizeBaseUrl(options?.baseUrl);
|
|
317
|
+
const envToken = process.env.SAASIGNAL_TOKEN?.trim();
|
|
318
|
+
if (envToken) {
|
|
319
|
+
return { token: envToken, baseUrl, source: "env_token" };
|
|
320
|
+
}
|
|
321
|
+
const storedProfile = await loadAuthProfile(options?.profilePath);
|
|
322
|
+
if (storedProfile && storedProfile.base_url === baseUrl && storedProfile.resource === baseUrl) {
|
|
323
|
+
try {
|
|
324
|
+
const profile = shouldRefreshProfile(storedProfile)
|
|
325
|
+
? await refreshAuthProfile(storedProfile, options?.fetchImpl ?? fetch)
|
|
326
|
+
: storedProfile;
|
|
327
|
+
if (profile !== storedProfile) {
|
|
328
|
+
await saveAuthProfile(profile, options?.profilePath);
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
token: profile.access_token,
|
|
332
|
+
baseUrl,
|
|
333
|
+
source: "stored_oauth",
|
|
334
|
+
profile,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
const apiKey = process.env.SAASIGNAL_API_KEY?.trim();
|
|
339
|
+
if (apiKey) {
|
|
340
|
+
return { token: apiKey, baseUrl, source: "env_api_key" };
|
|
341
|
+
}
|
|
342
|
+
throw new Error(`Stored SaaSignal login could not be refreshed. Run \`saasignal auth login\` again. ${error.message}`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
const apiKey = process.env.SAASIGNAL_API_KEY?.trim();
|
|
346
|
+
if (apiKey) {
|
|
347
|
+
return { token: apiKey, baseUrl, source: "env_api_key" };
|
|
348
|
+
}
|
|
349
|
+
throw new Error("No SaaSignal credentials found. Run `saasignal auth login`, set SAASIGNAL_TOKEN, or set SAASIGNAL_API_KEY.");
|
|
350
|
+
}
|
|
351
|
+
export async function revokeAndDeleteAuthProfile(profile, fetchImpl = fetch, path = getAuthConfigPath()) {
|
|
352
|
+
if (profile?.revocation_endpoint) {
|
|
353
|
+
try {
|
|
354
|
+
await postForm(fetchImpl, profile.revocation_endpoint, new URLSearchParams({
|
|
355
|
+
token: profile.refresh_token,
|
|
356
|
+
client_id: profile.client_id,
|
|
357
|
+
}));
|
|
358
|
+
}
|
|
359
|
+
catch {
|
|
360
|
+
// Best-effort revoke.
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
await deleteAuthProfile(path);
|
|
364
|
+
}
|
|
365
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { authorizeWithBrowser, loadAuthProfile, refreshAuthProfile, resolveCliAuth, revokeAndDeleteAuthProfile, saveAuthProfile } from "./auth.js";
|
|
2
3
|
import { SaaSignalClient, SaaSignalError } from "./client.js";
|
|
3
4
|
const USAGE = `
|
|
4
5
|
saasignal — CLI for the SaaSignal API
|
|
@@ -7,10 +8,12 @@ Usage:
|
|
|
7
8
|
saasignal <namespace> <command> [args...]
|
|
8
9
|
|
|
9
10
|
Environment:
|
|
10
|
-
|
|
11
|
+
SAASIGNAL_TOKEN Bearer token override (highest precedence)
|
|
12
|
+
SAASIGNAL_API_KEY API key fallback
|
|
11
13
|
SAASIGNAL_API_URL Base URL (default: https://api.saasignal.saastemly.com)
|
|
12
14
|
|
|
13
15
|
Namespaces:
|
|
16
|
+
auth Browser login, logout, and status
|
|
14
17
|
kv Key-value store
|
|
15
18
|
channels Real-time pub/sub
|
|
16
19
|
jobs Task / queue / cron
|
|
@@ -71,6 +74,11 @@ Delivery Commands:
|
|
|
71
74
|
delivery eta-fences delete <fence_id>
|
|
72
75
|
delivery settings
|
|
73
76
|
delivery analytics [--from <date>] [--to <date>]
|
|
77
|
+
|
|
78
|
+
Auth Commands:
|
|
79
|
+
auth login
|
|
80
|
+
auth logout
|
|
81
|
+
auth status
|
|
74
82
|
`.trim();
|
|
75
83
|
function parseArgs(args) {
|
|
76
84
|
const positional = [];
|
|
@@ -95,55 +103,124 @@ function parseArgs(args) {
|
|
|
95
103
|
function out(data) {
|
|
96
104
|
console.log(JSON.stringify(data, null, 2));
|
|
97
105
|
}
|
|
106
|
+
async function handleAuth(command) {
|
|
107
|
+
switch (command) {
|
|
108
|
+
case "login": {
|
|
109
|
+
let printedUrl = false;
|
|
110
|
+
const profile = await authorizeWithBrowser({
|
|
111
|
+
onAuthorizeUrl: (url) => {
|
|
112
|
+
printedUrl = true;
|
|
113
|
+
console.error("Opening the SaaSignal browser authorization flow...");
|
|
114
|
+
console.error(`If the browser does not open automatically, visit:\n${url}`);
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
await saveAuthProfile(profile);
|
|
118
|
+
out({
|
|
119
|
+
logged_in: true,
|
|
120
|
+
base_url: profile.base_url,
|
|
121
|
+
resource: profile.resource,
|
|
122
|
+
org_id: profile.org_id,
|
|
123
|
+
project_id: profile.project_id,
|
|
124
|
+
scopes: profile.scopes,
|
|
125
|
+
expires_at: profile.expires_at,
|
|
126
|
+
});
|
|
127
|
+
if (!printedUrl) {
|
|
128
|
+
console.error("SaaSignal browser authorization completed.");
|
|
129
|
+
}
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
case "logout": {
|
|
133
|
+
const profile = await loadAuthProfile();
|
|
134
|
+
await revokeAndDeleteAuthProfile(profile);
|
|
135
|
+
out({ logged_in: false });
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
case "status": {
|
|
139
|
+
const profile = await loadAuthProfile();
|
|
140
|
+
if (!profile) {
|
|
141
|
+
out({ logged_in: false });
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
out({
|
|
145
|
+
logged_in: true,
|
|
146
|
+
base_url: profile.base_url,
|
|
147
|
+
resource: profile.resource,
|
|
148
|
+
org_id: profile.org_id,
|
|
149
|
+
project_id: profile.project_id,
|
|
150
|
+
scopes: profile.scopes,
|
|
151
|
+
expires_at: profile.expires_at,
|
|
152
|
+
expired: new Date(profile.expires_at).getTime() <= Date.now(),
|
|
153
|
+
});
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
default:
|
|
157
|
+
console.error(`Unknown auth command: ${command}`);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async function executeNamespaceCommand(client, namespace, command, positional, flags) {
|
|
162
|
+
switch (namespace) {
|
|
163
|
+
case "kv":
|
|
164
|
+
await handleKv(client, command, positional, flags);
|
|
165
|
+
break;
|
|
166
|
+
case "channels":
|
|
167
|
+
await handleChannels(client, command, positional, flags);
|
|
168
|
+
break;
|
|
169
|
+
case "jobs":
|
|
170
|
+
await handleJobs(client, command, positional, flags);
|
|
171
|
+
break;
|
|
172
|
+
case "billing":
|
|
173
|
+
await handleBilling(client, command, positional, flags);
|
|
174
|
+
break;
|
|
175
|
+
case "storage":
|
|
176
|
+
await handleStorage(client, command, positional, flags);
|
|
177
|
+
break;
|
|
178
|
+
case "delivery":
|
|
179
|
+
await handleDelivery(client, command, positional, flags);
|
|
180
|
+
break;
|
|
181
|
+
default:
|
|
182
|
+
console.error(`Unknown namespace: ${namespace}\n`);
|
|
183
|
+
console.log(USAGE);
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
98
187
|
async function main() {
|
|
99
188
|
const args = process.argv.slice(2);
|
|
100
189
|
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
101
190
|
console.log(USAGE);
|
|
102
191
|
process.exit(0);
|
|
103
192
|
}
|
|
104
|
-
let client;
|
|
105
|
-
try {
|
|
106
|
-
client = new SaaSignalClient();
|
|
107
|
-
}
|
|
108
|
-
catch (e) {
|
|
109
|
-
console.error(`Error: ${e.message}`);
|
|
110
|
-
process.exit(1);
|
|
111
|
-
return; // unreachable but satisfies TS control flow
|
|
112
|
-
}
|
|
113
193
|
const [namespace, command, ...rest] = args;
|
|
114
194
|
const { positional, flags } = parseArgs(rest);
|
|
115
195
|
try {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
await
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
break;
|
|
135
|
-
default:
|
|
136
|
-
console.error(`Unknown namespace: ${namespace}\n`);
|
|
137
|
-
console.log(USAGE);
|
|
138
|
-
process.exit(1);
|
|
196
|
+
if (namespace === "auth") {
|
|
197
|
+
await handleAuth(command);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const resolvedAuth = await resolveCliAuth();
|
|
201
|
+
let client = new SaaSignalClient({ token: resolvedAuth.token, baseUrl: resolvedAuth.baseUrl });
|
|
202
|
+
try {
|
|
203
|
+
await executeNamespaceCommand(client, namespace, command, positional, flags);
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
if (error instanceof SaaSignalError && error.status === 401 && resolvedAuth.profile) {
|
|
207
|
+
const refreshedProfile = await refreshAuthProfile(resolvedAuth.profile);
|
|
208
|
+
await saveAuthProfile(refreshedProfile);
|
|
209
|
+
client = new SaaSignalClient({ token: refreshedProfile.access_token, baseUrl: resolvedAuth.baseUrl });
|
|
210
|
+
await executeNamespaceCommand(client, namespace, command, positional, flags);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
throw error;
|
|
139
214
|
}
|
|
140
215
|
}
|
|
141
216
|
catch (e) {
|
|
142
217
|
if (e instanceof SaaSignalError) {
|
|
143
218
|
console.error(JSON.stringify({ error: e.code, message: e.message, status: e.status }, null, 2));
|
|
144
219
|
process.exit(1);
|
|
220
|
+
return;
|
|
145
221
|
}
|
|
146
|
-
|
|
222
|
+
console.error(`Error: ${e.message}`);
|
|
223
|
+
process.exit(1);
|
|
147
224
|
}
|
|
148
225
|
}
|
|
149
226
|
async function handleKv(client, cmd, pos, flags) {
|