buildless-cli 0.1.8 → 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.
Files changed (46) hide show
  1. package/README.md +0 -20
  2. package/dist/index.js +2347 -83
  3. package/dist/index.js.map +1 -1
  4. package/package.json +4 -3
  5. package/dist/ai.d.ts +0 -8
  6. package/dist/ai.d.ts.map +0 -1
  7. package/dist/ai.js +0 -25
  8. package/dist/ai.js.map +0 -1
  9. package/dist/app.d.ts +0 -9
  10. package/dist/app.d.ts.map +0 -1
  11. package/dist/app.js +0 -67
  12. package/dist/app.js.map +0 -1
  13. package/dist/auth.d.ts +0 -14
  14. package/dist/auth.d.ts.map +0 -1
  15. package/dist/auth.js +0 -100
  16. package/dist/auth.js.map +0 -1
  17. package/dist/config.d.ts +0 -14
  18. package/dist/config.d.ts.map +0 -1
  19. package/dist/config.js +0 -45
  20. package/dist/config.js.map +0 -1
  21. package/dist/firestore.d.ts +0 -28
  22. package/dist/firestore.d.ts.map +0 -1
  23. package/dist/firestore.js +0 -340
  24. package/dist/firestore.js.map +0 -1
  25. package/dist/index.d.ts +0 -3
  26. package/dist/index.d.ts.map +0 -1
  27. package/dist/log.d.ts +0 -3
  28. package/dist/log.d.ts.map +0 -1
  29. package/dist/log.js +0 -10
  30. package/dist/log.js.map +0 -1
  31. package/dist/ui/app-search.d.ts +0 -11
  32. package/dist/ui/app-search.d.ts.map +0 -1
  33. package/dist/ui/app-search.js +0 -83
  34. package/dist/ui/app-search.js.map +0 -1
  35. package/dist/ui/runner.d.ts +0 -14
  36. package/dist/ui/runner.d.ts.map +0 -1
  37. package/dist/ui/runner.js +0 -506
  38. package/dist/ui/runner.js.map +0 -1
  39. package/dist/ui/useRunnerRenderSource.d.ts +0 -53
  40. package/dist/ui/useRunnerRenderSource.d.ts.map +0 -1
  41. package/dist/ui/useRunnerRenderSource.js +0 -69
  42. package/dist/ui/useRunnerRenderSource.js.map +0 -1
  43. package/dist/ui/useRunnerSession.d.ts +0 -16
  44. package/dist/ui/useRunnerSession.d.ts.map +0 -1
  45. package/dist/ui/useRunnerSession.js +0 -188
  46. package/dist/ui/useRunnerSession.js.map +0 -1
package/dist/app.js DELETED
@@ -1,67 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useState } from "react";
3
- import { Box, Text } from "ink";
4
- import { fetchRunnableAppsViaServer } from "./firestore.js";
5
- import { AppSearch } from "./ui/app-search.js";
6
- import { Runner } from "./ui/runner.js";
7
- import { log } from "./log.js";
8
- export const App = ({ config, idToken, initialQuery, onExit }) => {
9
- const [apps, setApps] = useState([]);
10
- const [loading, setLoading] = useState(true);
11
- const [error, setError] = useState(null);
12
- const [selectedApp, setSelectedApp] = useState(null);
13
- useEffect(() => {
14
- let mounted = true;
15
- const load = async () => {
16
- try {
17
- setLoading(true);
18
- log(`Loading apps from ${config.terminalUrl}`);
19
- const results = await fetchRunnableAppsViaServer({
20
- terminalUrl: config.terminalUrl,
21
- idToken,
22
- query: initialQuery,
23
- });
24
- if (!mounted)
25
- return;
26
- log(`Loaded ${results.length} apps`);
27
- setApps(results);
28
- setError(null);
29
- }
30
- catch (err) {
31
- if (!mounted)
32
- return;
33
- setError(err instanceof Error ? err.message : String(err));
34
- }
35
- finally {
36
- if (mounted)
37
- setLoading(false);
38
- }
39
- };
40
- void load();
41
- return () => {
42
- mounted = false;
43
- };
44
- }, [config.firebaseProjectId, config.terminalUrl, idToken, initialQuery]);
45
- if (error) {
46
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "red", children: error }), _jsx(Text, { dimColor: true, children: "Tip: Set BLO_DEBUG=1 for detailed logs." }), _jsx(Text, { children: "Press Ctrl+C to exit." })] }));
47
- }
48
- if (loading) {
49
- return (_jsx(Box, { flexDirection: "column", children: _jsxs(Text, { color: "green", children: ["Loading apps from ", config.terminalUrl, "..."] }) }));
50
- }
51
- if (apps.length === 0) {
52
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "yellow", children: "No apps found." }), _jsx(Text, { dimColor: true, children: initialQuery
53
- ? `No apps matched "${initialQuery}". Try without a query filter.`
54
- : "Your account has no projects and no published apps are available." }), _jsx(Text, { children: "Press Ctrl+C to exit." })] }));
55
- }
56
- if (!selectedApp) {
57
- return (_jsx(AppSearch, { apps: apps, initialQuery: initialQuery, onSelect: (app) => {
58
- log(`Selected app: ${app.projectId} (version=${app.versionId}, source=${app.versionSource})`);
59
- setSelectedApp(app);
60
- }, onExit: onExit }));
61
- }
62
- return (_jsx(Runner, { projectId: selectedApp.projectId, versionId: selectedApp.versionId, terminalUrl: config.terminalUrl, idToken: idToken, firebaseProjectId: config.firebaseProjectId, appCheckToken: config.appCheckToken, onBackToApps: () => {
63
- log("Returning to app list");
64
- setSelectedApp(null);
65
- }, onExit: onExit }));
66
- };
67
- //# sourceMappingURL=app.js.map
package/dist/app.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"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"}
package/dist/auth.d.ts DELETED
@@ -1,14 +0,0 @@
1
- export type LoginResult = {
2
- token: string;
3
- exp: number | null;
4
- appCheckToken?: string;
5
- };
6
- type LoginOptions = {
7
- webOrigin: string;
8
- };
9
- export declare const decodeJwtPayload: (token: string) => Record<string, unknown> | null;
10
- export declare const getTokenExp: (token: string) => number | null;
11
- export declare const isTokenValid: (token?: string, exp?: number | null) => boolean;
12
- export declare const startExternalLogin: (options: LoginOptions) => Promise<LoginResult>;
13
- export {};
14
- //# sourceMappingURL=auth.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,WAAW,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExF,KAAK,YAAY,GAAG;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAS1E,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,KAAG,MAAM,GAAG,IAIpD,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,QAAQ,MAAM,EAAE,MAAM,MAAM,GAAG,IAAI,KAAG,OAKlE,CAAC;AAIF,eAAO,MAAM,kBAAkB,GAAU,SAAS,YAAY,KAAG,OAAO,CAAC,WAAW,CAqEnF,CAAC"}
package/dist/auth.js DELETED
@@ -1,100 +0,0 @@
1
- import { createServer } from "node:http";
2
- import crypto from "node:crypto";
3
- import { URL } from "node:url";
4
- import open from "open";
5
- import { log } from "./log.js";
6
- export const decodeJwtPayload = (token) => {
7
- const parts = token.split(".");
8
- if (parts.length < 2)
9
- return null;
10
- try {
11
- const payload = Buffer.from(parts[1], "base64url").toString("utf8");
12
- return JSON.parse(payload);
13
- }
14
- catch {
15
- return null;
16
- }
17
- };
18
- export const getTokenExp = (token) => {
19
- const payload = decodeJwtPayload(token);
20
- if (!payload || typeof payload.exp !== "number")
21
- return null;
22
- return payload.exp;
23
- };
24
- export const isTokenValid = (token, exp) => {
25
- if (!token)
26
- return false;
27
- if (exp == null)
28
- return true;
29
- const now = Math.floor(Date.now() / 1000);
30
- return exp - 30 > now;
31
- };
32
- const LOGIN_TIMEOUT_MS = 120_000;
33
- export const startExternalLogin = async (options) => {
34
- const state = crypto.randomBytes(16).toString("hex");
35
- const server = createServer();
36
- const result = await new Promise((resolve, reject) => {
37
- let settled = false;
38
- const timeout = setTimeout(() => {
39
- if (settled)
40
- return;
41
- settled = true;
42
- server.close();
43
- reject(new Error("Login timed out after 2 minutes. Please try again."));
44
- }, LOGIN_TIMEOUT_MS);
45
- server.on("request", (req, res) => {
46
- if (!req.url)
47
- return;
48
- const url = new URL(req.url, "http://localhost");
49
- if (url.pathname !== "/callback") {
50
- res.writeHead(404, { "Content-Type": "text/plain" });
51
- res.end("Not found");
52
- return;
53
- }
54
- if (settled) {
55
- res.writeHead(409, { "Content-Type": "text/plain" });
56
- res.end("Login already handled. You can close this window.");
57
- return;
58
- }
59
- const token = url.searchParams.get("token") || "";
60
- const returnedState = url.searchParams.get("state") || "";
61
- const appCheckToken = url.searchParams.get("appCheckToken") || undefined;
62
- if (!token || returnedState !== state) {
63
- settled = true;
64
- res.writeHead(400, { "Content-Type": "text/plain" });
65
- res.end("Invalid login response. You can close this window.");
66
- clearTimeout(timeout);
67
- log(`Login callback failed: token=${token ? "present" : "missing"}, state=${returnedState === state ? "match" : "mismatch"}`);
68
- reject(new Error("Login failed: invalid callback. Make sure you completed the login in your browser."));
69
- server.close();
70
- return;
71
- }
72
- settled = true;
73
- res.writeHead(200, { "Content-Type": "text/plain" });
74
- res.end("Login complete. You can close this window.");
75
- clearTimeout(timeout);
76
- const exp = getTokenExp(token);
77
- log(`Login callback received: exp=${exp}, appCheck=${appCheckToken ? "yes" : "no"}`);
78
- resolve({ token, exp, appCheckToken });
79
- server.close();
80
- });
81
- server.listen(0, "127.0.0.1", () => {
82
- const address = server.address();
83
- if (!address || typeof address === "string") {
84
- clearTimeout(timeout);
85
- reject(new Error("Failed to start local login server."));
86
- return;
87
- }
88
- const callbackUrl = `http://127.0.0.1:${address.port}/callback`;
89
- const loginUrl = new URL("/cli-auth", options.webOrigin);
90
- loginUrl.searchParams.set("redirect_uri", callbackUrl);
91
- loginUrl.searchParams.set("state", state);
92
- log(`Login server listening on port ${address.port}`);
93
- log(`Opening browser: ${loginUrl.toString()}`);
94
- process.stderr.write("Opening browser for login...\n");
95
- void open(loginUrl.toString());
96
- });
97
- });
98
- return result;
99
- };
100
- //# sourceMappingURL=auth.js.map
package/dist/auth.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts DELETED
@@ -1,14 +0,0 @@
1
- export type CliConfig = {
2
- webOrigin: string;
3
- terminalUrl: string;
4
- firebaseProjectId: string;
5
- idToken?: string;
6
- tokenExp?: number;
7
- appCheckToken?: string;
8
- };
9
- export declare const loadConfig: () => {
10
- path: string;
11
- config: CliConfig;
12
- };
13
- export declare const saveConfig: (configPath: string, config: CliConfig) => void;
14
- //# sourceMappingURL=config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,SAAS,GAAG;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAcF,eAAO,MAAM,UAAU,QAAO;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,CAAA;CA0B9D,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,YAAY,MAAM,EAAE,QAAQ,SAAS,KAAG,IAIlE,CAAC"}
package/dist/config.js DELETED
@@ -1,45 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import os from "node:os";
4
- const defaultWebOrigin = process.env.BLO_WEB_ORIGIN || "https://buildless.online";
5
- const defaultTerminalUrl = process.env.BLO_TERMINAL_URL || "https://buildless.online";
6
- const defaultProjectId = process.env.BLO_FIREBASE_PROJECT_ID || process.env.VITE_FIREBASE_PROJECT_ID || "buildless-online";
7
- const resolveConfigPath = () => {
8
- if (process.env.BLO_CONFIG_PATH)
9
- return process.env.BLO_CONFIG_PATH;
10
- const home = os.homedir();
11
- const configDir = process.env.XDG_CONFIG_HOME || path.join(home, ".config");
12
- return path.join(configDir, "blo", "cli.json");
13
- };
14
- export const loadConfig = () => {
15
- const configPath = resolveConfigPath();
16
- const defaults = {
17
- webOrigin: defaultWebOrigin,
18
- terminalUrl: defaultTerminalUrl,
19
- firebaseProjectId: defaultProjectId,
20
- };
21
- if (!fs.existsSync(configPath)) {
22
- return { path: configPath, config: defaults };
23
- }
24
- try {
25
- const raw = fs.readFileSync(configPath, "utf8");
26
- const parsed = JSON.parse(raw);
27
- return {
28
- path: configPath,
29
- config: {
30
- ...defaults,
31
- ...parsed,
32
- },
33
- };
34
- }
35
- catch (err) {
36
- process.stderr.write(`Warning: failed to parse ${configPath}, using defaults: ${err instanceof Error ? err.message : String(err)}\n`);
37
- return { path: configPath, config: defaults };
38
- }
39
- };
40
- export const saveConfig = (configPath, config) => {
41
- const dir = path.dirname(configPath);
42
- fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
43
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 0o600 });
44
- };
45
- //# sourceMappingURL=config.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAWzB,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,0BAA0B,CAAC;AAClF,MAAM,kBAAkB,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,0BAA0B,CAAC;AACtF,MAAM,gBAAgB,GACpB,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,kBAAkB,CAAC;AAEpG,MAAM,iBAAiB,GAAG,GAAW,EAAE;IACrC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IACpE,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC1B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC5E,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,GAAwC,EAAE;IAClE,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAc;QAC1B,SAAS,EAAE,gBAAgB;QAC3B,WAAW,EAAE,kBAAkB;QAC/B,iBAAiB,EAAE,gBAAgB;KACpC,CAAC;IAEF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAChD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAuB,CAAC;QACrD,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE;gBACN,GAAG,QAAQ;gBACX,GAAG,MAAM;aACV;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,UAAU,qBAAqB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtI,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAChD,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,UAAkB,EAAE,MAAiB,EAAQ,EAAE;IACxE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACrC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACpD,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACjF,CAAC,CAAC"}
@@ -1,28 +0,0 @@
1
- export type RunnableApp = {
2
- id: string;
3
- projectId: string;
4
- versionId: string;
5
- versionSource: "published" | "latest" | "store";
6
- publishedVersionId?: string;
7
- name?: string;
8
- displayName?: string;
9
- tagline?: string;
10
- description?: string;
11
- accessTier?: string;
12
- authorName?: string;
13
- ownerDisplayName?: string;
14
- appSource?: "user" | "published";
15
- };
16
- export declare const fetchRunnableAppsViaServer: (opts: {
17
- terminalUrl: string;
18
- idToken: string;
19
- query?: string;
20
- }) => Promise<RunnableApp[]>;
21
- export declare const fetchRunnableApps: (opts: {
22
- projectId: string;
23
- idToken: string;
24
- appCheckToken?: string;
25
- query?: string;
26
- }) => Promise<RunnableApp[]>;
27
- export declare const filterApp: (app: RunnableApp, term: string) => boolean;
28
- //# sourceMappingURL=firestore.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore.d.ts","sourceRoot":"","sources":["../src/firestore.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;IAChD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;CAClC,CAAC;AA4TF,eAAO,MAAM,0BAA0B,GAAU,MAAM;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,KAAG,OAAO,CAAC,WAAW,EAAE,CAoCxB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,MAAM;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,KAAG,OAAO,CAAC,WAAW,EAAE,CA+BxB,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,KAAK,WAAW,EAAE,MAAM,MAAM,KAAG,OAaK,CAAC"}
package/dist/firestore.js DELETED
@@ -1,340 +0,0 @@
1
- import { decodeJwtPayload } from "./auth.js";
2
- import { log } from "./log.js";
3
- const resolveUidFromToken = (idToken) => {
4
- const payload = decodeJwtPayload(idToken);
5
- if (!payload)
6
- return null;
7
- const uid = payload.user_id ?? payload.sub;
8
- return typeof uid === "string" && uid.trim() ? uid.trim() : null;
9
- };
10
- const fromFirestoreValue = (value) => {
11
- if (value == null || typeof value !== "object")
12
- return null;
13
- if ("stringValue" in value)
14
- return String(value.stringValue);
15
- if ("booleanValue" in value)
16
- return Boolean(value.booleanValue);
17
- if ("integerValue" in value)
18
- return Number(value.integerValue);
19
- if ("doubleValue" in value)
20
- return Number(value.doubleValue);
21
- if ("timestampValue" in value)
22
- return String(value.timestampValue);
23
- if ("referenceValue" in value)
24
- return String(value.referenceValue);
25
- if ("mapValue" in value) {
26
- const fields = value.mapValue?.fields || {};
27
- const output = {};
28
- for (const [key, entry] of Object.entries(fields)) {
29
- output[key] = fromFirestoreValue(entry);
30
- }
31
- return output;
32
- }
33
- if ("arrayValue" in value) {
34
- const values = value.arrayValue?.values || [];
35
- return values.map(fromFirestoreValue);
36
- }
37
- if ("nullValue" in value)
38
- return null;
39
- return null;
40
- };
41
- const parseDocument = (doc) => {
42
- const fields = doc?.fields || {};
43
- const output = {};
44
- for (const [key, entry] of Object.entries(fields)) {
45
- output[key] = fromFirestoreValue(entry);
46
- }
47
- return output;
48
- };
49
- const firestoreDocsBase = (projectId) => `https://firestore.googleapis.com/v1/projects/${encodeURIComponent(projectId)}/databases/(default)/documents`;
50
- const parseRunQueryDocs = (rows) => rows.map((row) => row.document).filter(Boolean);
51
- const extractDocIdFromName = (name) => {
52
- if (!name)
53
- return undefined;
54
- const chunks = String(name).split("/");
55
- return chunks[chunks.length - 1] || undefined;
56
- };
57
- const authHeaders = (idToken, appCheckToken) => {
58
- const headers = {
59
- Authorization: `Bearer ${idToken}`,
60
- };
61
- if (appCheckToken) {
62
- headers["X-Firebase-AppCheck"] = appCheckToken;
63
- }
64
- return headers;
65
- };
66
- const fetchPublishedApps = async (opts) => {
67
- const { projectId, idToken, appCheckToken } = opts;
68
- const endpoint = `${firestoreDocsBase(projectId)}:runQuery`;
69
- const body = {
70
- structuredQuery: {
71
- from: [{ collectionId: "publishedApps" }],
72
- where: {
73
- fieldFilter: {
74
- field: { fieldPath: "isPublished" },
75
- op: "EQUAL",
76
- value: { booleanValue: true },
77
- },
78
- },
79
- limit: 250,
80
- },
81
- };
82
- const response = await fetch(endpoint, {
83
- method: "POST",
84
- headers: {
85
- "Content-Type": "application/json",
86
- ...authHeaders(idToken, appCheckToken),
87
- },
88
- body: JSON.stringify(body),
89
- });
90
- if (!response.ok) {
91
- const text = await response.text();
92
- log(`Failed to fetch published apps (${response.status}): ${text}`);
93
- throw new Error(`Failed to fetch published apps (${response.status})`);
94
- }
95
- const rows = (await response.json());
96
- const mapped = parseRunQueryDocs(rows).map((doc) => {
97
- const data = parseDocument(doc);
98
- const projectIdFromDoc = String(data.projectId || "").trim();
99
- const publishedVersionId = String(data.publishedVersionId || "").trim();
100
- if (!projectIdFromDoc || !publishedVersionId)
101
- return null;
102
- return {
103
- id: projectIdFromDoc,
104
- projectId: projectIdFromDoc,
105
- versionId: publishedVersionId,
106
- versionSource: "store",
107
- publishedVersionId,
108
- name: data.name ? String(data.name) : undefined,
109
- displayName: data.displayName ? String(data.displayName) : undefined,
110
- tagline: data.tagline ? String(data.tagline) : undefined,
111
- description: data.description ? String(data.description) : undefined,
112
- accessTier: data.accessTier ? String(data.accessTier) : undefined,
113
- authorName: data.authorName ? String(data.authorName) : undefined,
114
- ownerDisplayName: data.ownerDisplayName ? String(data.ownerDisplayName) : undefined,
115
- appSource: "published",
116
- };
117
- });
118
- return mapped.filter((entry) => entry !== null);
119
- };
120
- const fetchUserProjectIds = async (opts) => {
121
- const { projectId, idToken, appCheckToken, uid } = opts;
122
- const endpoint = `${firestoreDocsBase(projectId)}/users/${encodeURIComponent(uid)}`;
123
- const response = await fetch(endpoint, {
124
- headers: authHeaders(idToken, appCheckToken),
125
- });
126
- if (response.status === 404)
127
- return [];
128
- if (!response.ok) {
129
- const text = await response.text();
130
- log(`Failed to fetch user profile (${response.status}): ${text}`);
131
- throw new Error(`Failed to fetch user profile (${response.status})`);
132
- }
133
- const doc = (await response.json());
134
- const data = parseDocument(doc);
135
- const projectAccess = data.projectAccess && typeof data.projectAccess === "object"
136
- ? data.projectAccess
137
- : {};
138
- return Object.keys(projectAccess);
139
- };
140
- const fetchProjectDoc = async (opts) => {
141
- const { projectId, idToken, appCheckToken, targetProjectId } = opts;
142
- const endpoint = `${firestoreDocsBase(projectId)}/projects/${encodeURIComponent(targetProjectId)}`;
143
- const response = await fetch(endpoint, {
144
- headers: authHeaders(idToken, appCheckToken),
145
- });
146
- if (response.status === 404)
147
- return null;
148
- if (!response.ok) {
149
- const text = await response.text();
150
- log(`Failed to fetch project ${targetProjectId} (${response.status}): ${text}`);
151
- throw new Error(`Failed to fetch project ${targetProjectId} (${response.status})`);
152
- }
153
- const doc = (await response.json());
154
- return parseDocument(doc);
155
- };
156
- const fetchLatestVersionId = async (opts) => {
157
- const { projectId, idToken, appCheckToken, targetProjectId } = opts;
158
- const endpoint = `${firestoreDocsBase(projectId)}/projects/${encodeURIComponent(targetProjectId)}:runQuery`;
159
- const tryQueries = [
160
- {
161
- structuredQuery: {
162
- from: [{ collectionId: "versions" }],
163
- orderBy: [{ field: { fieldPath: "updatedAt" }, direction: "DESCENDING" }],
164
- limit: 1,
165
- },
166
- },
167
- {
168
- structuredQuery: {
169
- from: [{ collectionId: "versions" }],
170
- orderBy: [{ field: { fieldPath: "createdAt" }, direction: "DESCENDING" }],
171
- limit: 1,
172
- },
173
- },
174
- {
175
- structuredQuery: {
176
- from: [{ collectionId: "versions" }],
177
- limit: 1,
178
- },
179
- },
180
- ];
181
- for (const body of tryQueries) {
182
- const response = await fetch(endpoint, {
183
- method: "POST",
184
- headers: {
185
- "Content-Type": "application/json",
186
- ...authHeaders(idToken, appCheckToken),
187
- },
188
- body: JSON.stringify(body),
189
- });
190
- if (!response.ok) {
191
- continue;
192
- }
193
- const rows = (await response.json());
194
- const doc = parseRunQueryDocs(rows)[0];
195
- const docId = extractDocIdFromName(doc?.name);
196
- if (docId)
197
- return docId;
198
- }
199
- return null;
200
- };
201
- const mapProjectToRunnableApp = async (opts) => {
202
- const { projectId, idToken, appCheckToken, targetProjectId } = opts;
203
- const projectDoc = await fetchProjectDoc({ projectId, idToken, appCheckToken, targetProjectId });
204
- if (!projectDoc)
205
- return null;
206
- const publishedVersionId = String(projectDoc.publishedVersionId || "").trim();
207
- const latestVersionId = publishedVersionId ||
208
- (await fetchLatestVersionId({ projectId, idToken, appCheckToken, targetProjectId })) ||
209
- "";
210
- const versionId = String(latestVersionId || "").trim();
211
- if (!versionId)
212
- return null;
213
- const ownerData = projectDoc.ownerData && typeof projectDoc.ownerData === "object"
214
- ? projectDoc.ownerData
215
- : {};
216
- return {
217
- id: targetProjectId,
218
- projectId: targetProjectId,
219
- versionId,
220
- versionSource: publishedVersionId ? "published" : "latest",
221
- publishedVersionId: publishedVersionId || undefined,
222
- name: projectDoc.name ? String(projectDoc.name) : undefined,
223
- displayName: projectDoc.displayName ? String(projectDoc.displayName) : undefined,
224
- description: projectDoc.description ? String(projectDoc.description) : undefined,
225
- accessTier: projectDoc.accessTier ? String(projectDoc.accessTier) : undefined,
226
- authorName: projectDoc.authorName ? String(projectDoc.authorName) : undefined,
227
- ownerDisplayName: (typeof ownerData.displayName === "string" ? ownerData.displayName : undefined) ||
228
- (projectDoc.owner ? String(projectDoc.owner) : undefined),
229
- appSource: "user",
230
- };
231
- };
232
- const fetchUserApps = async (opts) => {
233
- const uid = resolveUidFromToken(opts.idToken);
234
- if (!uid) {
235
- throw new Error("Failed to decode uid from Firebase ID token.");
236
- }
237
- const projectIds = await fetchUserProjectIds({
238
- projectId: opts.projectId,
239
- idToken: opts.idToken,
240
- appCheckToken: opts.appCheckToken,
241
- uid,
242
- });
243
- if (!projectIds.length)
244
- return [];
245
- const results = await Promise.allSettled(projectIds.map((targetProjectId) => mapProjectToRunnableApp({
246
- projectId: opts.projectId,
247
- idToken: opts.idToken,
248
- appCheckToken: opts.appCheckToken,
249
- targetProjectId,
250
- })));
251
- const apps = [];
252
- for (const result of results) {
253
- if (result.status === "fulfilled" && result.value) {
254
- apps.push(result.value);
255
- }
256
- else if (result.status === "rejected") {
257
- process.stderr.write(`Warning: failed to load a project: ${result.reason}\n`);
258
- }
259
- }
260
- return apps;
261
- };
262
- export const fetchRunnableAppsViaServer = async (opts) => {
263
- const { terminalUrl, idToken, query } = opts;
264
- const url = new URL("/api/apps", terminalUrl);
265
- if (query)
266
- url.searchParams.set("q", query);
267
- log(`Fetching apps: GET ${url.toString()}`);
268
- const response = await fetch(url.toString(), {
269
- headers: { Authorization: `Bearer ${idToken}` },
270
- });
271
- if (!response.ok) {
272
- let message;
273
- try {
274
- const body = await response.json();
275
- message = body.message;
276
- }
277
- catch {
278
- // ignore parse errors
279
- }
280
- log(`Fetch apps failed: ${response.status} ${message || "(no message)"}`);
281
- if (response.status === 401) {
282
- throw new Error("Authentication failed. Try 'blo login' to re-authenticate.");
283
- }
284
- if (response.status === 403 && message?.toLowerCase().includes("cli access")) {
285
- const uid = resolveUidFromToken(idToken) || "unknown";
286
- throw new Error(`CLI access is not enabled for your account (uid: ${uid}). Contact an admin to enable it.`);
287
- }
288
- if (response.status >= 500) {
289
- throw new Error(`Server error (${response.status}). The terminal server may be having issues.`);
290
- }
291
- throw new Error(message || `Failed to fetch apps (${response.status})`);
292
- }
293
- const body = (await response.json());
294
- const apps = body.apps || [];
295
- log(`Fetched ${apps.length} apps`);
296
- return apps;
297
- };
298
- export const fetchRunnableApps = async (opts) => {
299
- const { projectId, idToken, appCheckToken, query } = opts;
300
- const userApps = await fetchUserApps({ projectId, idToken, appCheckToken });
301
- let publishedApps = [];
302
- try {
303
- publishedApps = await fetchPublishedApps({ projectId, idToken, appCheckToken });
304
- }
305
- catch (err) {
306
- process.stderr.write(`Warning: failed to fetch published apps: ${err}\n`);
307
- }
308
- const byProjectId = new Map();
309
- userApps.forEach((app) => {
310
- byProjectId.set(app.projectId, app);
311
- });
312
- publishedApps.forEach((app) => {
313
- if (!byProjectId.has(app.projectId)) {
314
- byProjectId.set(app.projectId, app);
315
- }
316
- });
317
- const allApps = Array.from(byProjectId.values()).sort((a, b) => {
318
- const aName = String(a.name || a.projectId).toLowerCase();
319
- const bName = String(b.name || b.projectId).toLowerCase();
320
- return aName.localeCompare(bName);
321
- });
322
- const term = (query || "").trim().toLowerCase();
323
- if (!term)
324
- return allApps;
325
- return allApps.filter((app) => filterApp(app, term));
326
- };
327
- export const filterApp = (app, term) => [
328
- app.projectId,
329
- app.displayName,
330
- app.name,
331
- app.tagline,
332
- app.description,
333
- app.authorName,
334
- app.ownerDisplayName,
335
- app.versionId,
336
- app.accessTier,
337
- ]
338
- .filter(Boolean)
339
- .some((field) => String(field).toLowerCase().includes(term));
340
- //# sourceMappingURL=firestore.js.map