clawfire 0.6.3 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1 -1
- package/dist/{dev-server-NWB66EJT.js → dev-server-LCKIGM6U.js} +133 -1
- package/dist/dev.cjs +132 -0
- package/dist/dev.cjs.map +1 -1
- package/dist/dev.js +133 -1
- package/dist/dev.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -269,7 +269,7 @@ async function runDevServer() {
|
|
|
269
269
|
const port = portArg ? parseInt(portArg.split("=")[1], 10) : 3e3;
|
|
270
270
|
const apiPort = apiPortArg ? parseInt(apiPortArg.split("=")[1], 10) : 3456;
|
|
271
271
|
const noHotReload = args.includes("--no-hot-reload");
|
|
272
|
-
const { startDevServer } = await import("./dev-server-
|
|
272
|
+
const { startDevServer } = await import("./dev-server-LCKIGM6U.js");
|
|
273
273
|
await startDevServer({
|
|
274
274
|
projectDir,
|
|
275
275
|
port,
|
|
@@ -2579,7 +2579,7 @@ function generateDashboardHtml(options) {
|
|
|
2579
2579
|
import { execFile as execFile2, spawn } from "child_process";
|
|
2580
2580
|
import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
2581
2581
|
import { resolve as resolve4, join as join3 } from "path";
|
|
2582
|
-
import { tmpdir, platform } from "os";
|
|
2582
|
+
import { tmpdir, platform, homedir } from "os";
|
|
2583
2583
|
var FirebaseSetup = class {
|
|
2584
2584
|
projectDir;
|
|
2585
2585
|
stateFilePath;
|
|
@@ -3003,8 +3003,119 @@ var FirebaseSetup = class {
|
|
|
3003
3003
|
return { success: true, message: `${service} enabled in firebase.json.` };
|
|
3004
3004
|
}
|
|
3005
3005
|
// ─── Firestore Database Automation ──────────────────────────────────
|
|
3006
|
+
/**
|
|
3007
|
+
* Read Firebase CLI's stored OAuth token and exchange for access token.
|
|
3008
|
+
* No gcloud CLI needed — uses the token from `firebase login`.
|
|
3009
|
+
*/
|
|
3010
|
+
async getFirebaseAccessToken() {
|
|
3011
|
+
const home = homedir();
|
|
3012
|
+
const configPath = join3(home, ".config", "configstore", "firebase-tools.json");
|
|
3013
|
+
if (!existsSync5(configPath)) return null;
|
|
3014
|
+
try {
|
|
3015
|
+
const config = JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
3016
|
+
let refreshToken = null;
|
|
3017
|
+
if (config?.activeAccounts) {
|
|
3018
|
+
const activeEmail = config?.user?.email;
|
|
3019
|
+
if (activeEmail && config.activeAccounts[activeEmail]?.tokens?.refresh_token) {
|
|
3020
|
+
refreshToken = config.activeAccounts[activeEmail].tokens.refresh_token;
|
|
3021
|
+
}
|
|
3022
|
+
if (!refreshToken) {
|
|
3023
|
+
for (const account of Object.values(config.activeAccounts)) {
|
|
3024
|
+
if (account?.tokens?.refresh_token) {
|
|
3025
|
+
refreshToken = account.tokens.refresh_token;
|
|
3026
|
+
break;
|
|
3027
|
+
}
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
if (!refreshToken && config?.tokens?.refresh_token) {
|
|
3032
|
+
refreshToken = config.tokens.refresh_token;
|
|
3033
|
+
}
|
|
3034
|
+
if (!refreshToken) return null;
|
|
3035
|
+
const body = new URLSearchParams({
|
|
3036
|
+
grant_type: "refresh_token",
|
|
3037
|
+
refresh_token: refreshToken,
|
|
3038
|
+
client_id: "563584335869-fgrhgmd47bqnekij5i8b5pr03ho849e6.apps.googleusercontent.com",
|
|
3039
|
+
client_secret: "j9iVZfS8kkCEFUPaAeJV0sAi"
|
|
3040
|
+
});
|
|
3041
|
+
const res = await fetch("https://oauth2.googleapis.com/token", {
|
|
3042
|
+
method: "POST",
|
|
3043
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
3044
|
+
body: body.toString()
|
|
3045
|
+
});
|
|
3046
|
+
if (res.ok) {
|
|
3047
|
+
const data = await res.json();
|
|
3048
|
+
return data.access_token || null;
|
|
3049
|
+
}
|
|
3050
|
+
} catch {
|
|
3051
|
+
}
|
|
3052
|
+
return null;
|
|
3053
|
+
}
|
|
3054
|
+
/**
|
|
3055
|
+
* Enable Firestore API using Google Service Usage REST API.
|
|
3056
|
+
* Uses Firebase CLI's stored auth token — no gcloud CLI needed.
|
|
3057
|
+
* Falls back to gcloud CLI, then manual URL.
|
|
3058
|
+
*/
|
|
3059
|
+
async enableFirestoreApi() {
|
|
3060
|
+
const state = this.loadState();
|
|
3061
|
+
let projectId = state.projectId || "";
|
|
3062
|
+
if (!projectId) {
|
|
3063
|
+
const firebasercPath = resolve4(this.projectDir, ".firebaserc");
|
|
3064
|
+
if (existsSync5(firebasercPath)) {
|
|
3065
|
+
try {
|
|
3066
|
+
const rc = JSON.parse(readFileSync4(firebasercPath, "utf-8"));
|
|
3067
|
+
projectId = rc?.projects?.default || "";
|
|
3068
|
+
} catch {
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
if (!projectId) {
|
|
3073
|
+
return { success: false, message: "No project ID found. Select a project first." };
|
|
3074
|
+
}
|
|
3075
|
+
try {
|
|
3076
|
+
const accessToken = await this.getFirebaseAccessToken();
|
|
3077
|
+
if (accessToken) {
|
|
3078
|
+
const res = await fetch(
|
|
3079
|
+
`https://serviceusage.googleapis.com/v1/projects/${projectId}/services/firestore.googleapis.com:enable`,
|
|
3080
|
+
{
|
|
3081
|
+
method: "POST",
|
|
3082
|
+
headers: {
|
|
3083
|
+
Authorization: `Bearer ${accessToken}`,
|
|
3084
|
+
"Content-Type": "application/json"
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
);
|
|
3088
|
+
if (res.ok) {
|
|
3089
|
+
return { success: true, message: "Firestore API enabled via REST API." };
|
|
3090
|
+
}
|
|
3091
|
+
if (res.status === 409) {
|
|
3092
|
+
return { success: true, message: "Firestore API already enabled." };
|
|
3093
|
+
}
|
|
3094
|
+
}
|
|
3095
|
+
} catch {
|
|
3096
|
+
}
|
|
3097
|
+
try {
|
|
3098
|
+
await this.execTimeout(
|
|
3099
|
+
"gcloud",
|
|
3100
|
+
["services", "enable", "firestore.googleapis.com", "--project", projectId],
|
|
3101
|
+
6e4
|
|
3102
|
+
);
|
|
3103
|
+
return { success: true, message: "Firestore API enabled via gcloud." };
|
|
3104
|
+
} catch (err) {
|
|
3105
|
+
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
3106
|
+
if (!(msg.includes("ENOENT") || msg.includes("not found") || msg.includes("command not found"))) {
|
|
3107
|
+
return { success: false, message: `Failed to enable Firestore API: ${msg}` };
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
return {
|
|
3111
|
+
success: false,
|
|
3112
|
+
message: `Failed to enable Firestore API automatically. Please enable it manually:
|
|
3113
|
+
https://console.developers.google.com/apis/api/firestore.googleapis.com/overview?project=${projectId}`
|
|
3114
|
+
};
|
|
3115
|
+
}
|
|
3006
3116
|
/**
|
|
3007
3117
|
* Create Firestore database via CLI.
|
|
3118
|
+
* Automatically enables Firestore API if needed.
|
|
3008
3119
|
* Handles "ALREADY_EXISTS" gracefully — returns success.
|
|
3009
3120
|
*/
|
|
3010
3121
|
async createFirestoreDatabase(location = "nam5") {
|
|
@@ -3020,6 +3131,27 @@ var FirebaseSetup = class {
|
|
|
3020
3131
|
if (msg.includes("ALREADY_EXISTS") || msg.includes("already exists")) {
|
|
3021
3132
|
return { success: true, message: "Firestore database already exists." };
|
|
3022
3133
|
}
|
|
3134
|
+
if (msg.includes("403") || msg.includes("has not been used") || msg.includes("is disabled")) {
|
|
3135
|
+
const enableResult = await this.enableFirestoreApi();
|
|
3136
|
+
if (!enableResult.success) {
|
|
3137
|
+
return enableResult;
|
|
3138
|
+
}
|
|
3139
|
+
await new Promise((r) => setTimeout(r, 5e3));
|
|
3140
|
+
try {
|
|
3141
|
+
await this.execTimeout(
|
|
3142
|
+
"firebase",
|
|
3143
|
+
["firestore:databases:create", "(default)", "--location", location, "--json"],
|
|
3144
|
+
6e4
|
|
3145
|
+
);
|
|
3146
|
+
return { success: true, message: `Firestore API enabled and database created (location: ${location}).` };
|
|
3147
|
+
} catch (retryErr) {
|
|
3148
|
+
const retryMsg = retryErr instanceof Error ? retryErr.message : "Unknown error";
|
|
3149
|
+
if (retryMsg.includes("ALREADY_EXISTS") || retryMsg.includes("already exists")) {
|
|
3150
|
+
return { success: true, message: "Firestore database already exists." };
|
|
3151
|
+
}
|
|
3152
|
+
return { success: false, message: `Failed to create Firestore database after enabling API: ${retryMsg}` };
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3023
3155
|
return { success: false, message: `Failed to create Firestore database: ${msg}` };
|
|
3024
3156
|
}
|
|
3025
3157
|
}
|
package/dist/dev.cjs
CHANGED
|
@@ -3415,8 +3415,119 @@ var FirebaseSetup = class {
|
|
|
3415
3415
|
return { success: true, message: `${service} enabled in firebase.json.` };
|
|
3416
3416
|
}
|
|
3417
3417
|
// ─── Firestore Database Automation ──────────────────────────────────
|
|
3418
|
+
/**
|
|
3419
|
+
* Read Firebase CLI's stored OAuth token and exchange for access token.
|
|
3420
|
+
* No gcloud CLI needed — uses the token from `firebase login`.
|
|
3421
|
+
*/
|
|
3422
|
+
async getFirebaseAccessToken() {
|
|
3423
|
+
const home = (0, import_node_os.homedir)();
|
|
3424
|
+
const configPath = (0, import_node_path4.join)(home, ".config", "configstore", "firebase-tools.json");
|
|
3425
|
+
if (!(0, import_node_fs4.existsSync)(configPath)) return null;
|
|
3426
|
+
try {
|
|
3427
|
+
const config = JSON.parse((0, import_node_fs4.readFileSync)(configPath, "utf-8"));
|
|
3428
|
+
let refreshToken = null;
|
|
3429
|
+
if (config?.activeAccounts) {
|
|
3430
|
+
const activeEmail = config?.user?.email;
|
|
3431
|
+
if (activeEmail && config.activeAccounts[activeEmail]?.tokens?.refresh_token) {
|
|
3432
|
+
refreshToken = config.activeAccounts[activeEmail].tokens.refresh_token;
|
|
3433
|
+
}
|
|
3434
|
+
if (!refreshToken) {
|
|
3435
|
+
for (const account of Object.values(config.activeAccounts)) {
|
|
3436
|
+
if (account?.tokens?.refresh_token) {
|
|
3437
|
+
refreshToken = account.tokens.refresh_token;
|
|
3438
|
+
break;
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3441
|
+
}
|
|
3442
|
+
}
|
|
3443
|
+
if (!refreshToken && config?.tokens?.refresh_token) {
|
|
3444
|
+
refreshToken = config.tokens.refresh_token;
|
|
3445
|
+
}
|
|
3446
|
+
if (!refreshToken) return null;
|
|
3447
|
+
const body = new URLSearchParams({
|
|
3448
|
+
grant_type: "refresh_token",
|
|
3449
|
+
refresh_token: refreshToken,
|
|
3450
|
+
client_id: "563584335869-fgrhgmd47bqnekij5i8b5pr03ho849e6.apps.googleusercontent.com",
|
|
3451
|
+
client_secret: "j9iVZfS8kkCEFUPaAeJV0sAi"
|
|
3452
|
+
});
|
|
3453
|
+
const res = await fetch("https://oauth2.googleapis.com/token", {
|
|
3454
|
+
method: "POST",
|
|
3455
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
3456
|
+
body: body.toString()
|
|
3457
|
+
});
|
|
3458
|
+
if (res.ok) {
|
|
3459
|
+
const data = await res.json();
|
|
3460
|
+
return data.access_token || null;
|
|
3461
|
+
}
|
|
3462
|
+
} catch {
|
|
3463
|
+
}
|
|
3464
|
+
return null;
|
|
3465
|
+
}
|
|
3466
|
+
/**
|
|
3467
|
+
* Enable Firestore API using Google Service Usage REST API.
|
|
3468
|
+
* Uses Firebase CLI's stored auth token — no gcloud CLI needed.
|
|
3469
|
+
* Falls back to gcloud CLI, then manual URL.
|
|
3470
|
+
*/
|
|
3471
|
+
async enableFirestoreApi() {
|
|
3472
|
+
const state = this.loadState();
|
|
3473
|
+
let projectId = state.projectId || "";
|
|
3474
|
+
if (!projectId) {
|
|
3475
|
+
const firebasercPath = (0, import_node_path4.resolve)(this.projectDir, ".firebaserc");
|
|
3476
|
+
if ((0, import_node_fs4.existsSync)(firebasercPath)) {
|
|
3477
|
+
try {
|
|
3478
|
+
const rc = JSON.parse((0, import_node_fs4.readFileSync)(firebasercPath, "utf-8"));
|
|
3479
|
+
projectId = rc?.projects?.default || "";
|
|
3480
|
+
} catch {
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
}
|
|
3484
|
+
if (!projectId) {
|
|
3485
|
+
return { success: false, message: "No project ID found. Select a project first." };
|
|
3486
|
+
}
|
|
3487
|
+
try {
|
|
3488
|
+
const accessToken = await this.getFirebaseAccessToken();
|
|
3489
|
+
if (accessToken) {
|
|
3490
|
+
const res = await fetch(
|
|
3491
|
+
`https://serviceusage.googleapis.com/v1/projects/${projectId}/services/firestore.googleapis.com:enable`,
|
|
3492
|
+
{
|
|
3493
|
+
method: "POST",
|
|
3494
|
+
headers: {
|
|
3495
|
+
Authorization: `Bearer ${accessToken}`,
|
|
3496
|
+
"Content-Type": "application/json"
|
|
3497
|
+
}
|
|
3498
|
+
}
|
|
3499
|
+
);
|
|
3500
|
+
if (res.ok) {
|
|
3501
|
+
return { success: true, message: "Firestore API enabled via REST API." };
|
|
3502
|
+
}
|
|
3503
|
+
if (res.status === 409) {
|
|
3504
|
+
return { success: true, message: "Firestore API already enabled." };
|
|
3505
|
+
}
|
|
3506
|
+
}
|
|
3507
|
+
} catch {
|
|
3508
|
+
}
|
|
3509
|
+
try {
|
|
3510
|
+
await this.execTimeout(
|
|
3511
|
+
"gcloud",
|
|
3512
|
+
["services", "enable", "firestore.googleapis.com", "--project", projectId],
|
|
3513
|
+
6e4
|
|
3514
|
+
);
|
|
3515
|
+
return { success: true, message: "Firestore API enabled via gcloud." };
|
|
3516
|
+
} catch (err) {
|
|
3517
|
+
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
3518
|
+
if (!(msg.includes("ENOENT") || msg.includes("not found") || msg.includes("command not found"))) {
|
|
3519
|
+
return { success: false, message: `Failed to enable Firestore API: ${msg}` };
|
|
3520
|
+
}
|
|
3521
|
+
}
|
|
3522
|
+
return {
|
|
3523
|
+
success: false,
|
|
3524
|
+
message: `Failed to enable Firestore API automatically. Please enable it manually:
|
|
3525
|
+
https://console.developers.google.com/apis/api/firestore.googleapis.com/overview?project=${projectId}`
|
|
3526
|
+
};
|
|
3527
|
+
}
|
|
3418
3528
|
/**
|
|
3419
3529
|
* Create Firestore database via CLI.
|
|
3530
|
+
* Automatically enables Firestore API if needed.
|
|
3420
3531
|
* Handles "ALREADY_EXISTS" gracefully — returns success.
|
|
3421
3532
|
*/
|
|
3422
3533
|
async createFirestoreDatabase(location = "nam5") {
|
|
@@ -3432,6 +3543,27 @@ var FirebaseSetup = class {
|
|
|
3432
3543
|
if (msg.includes("ALREADY_EXISTS") || msg.includes("already exists")) {
|
|
3433
3544
|
return { success: true, message: "Firestore database already exists." };
|
|
3434
3545
|
}
|
|
3546
|
+
if (msg.includes("403") || msg.includes("has not been used") || msg.includes("is disabled")) {
|
|
3547
|
+
const enableResult = await this.enableFirestoreApi();
|
|
3548
|
+
if (!enableResult.success) {
|
|
3549
|
+
return enableResult;
|
|
3550
|
+
}
|
|
3551
|
+
await new Promise((r) => setTimeout(r, 5e3));
|
|
3552
|
+
try {
|
|
3553
|
+
await this.execTimeout(
|
|
3554
|
+
"firebase",
|
|
3555
|
+
["firestore:databases:create", "(default)", "--location", location, "--json"],
|
|
3556
|
+
6e4
|
|
3557
|
+
);
|
|
3558
|
+
return { success: true, message: `Firestore API enabled and database created (location: ${location}).` };
|
|
3559
|
+
} catch (retryErr) {
|
|
3560
|
+
const retryMsg = retryErr instanceof Error ? retryErr.message : "Unknown error";
|
|
3561
|
+
if (retryMsg.includes("ALREADY_EXISTS") || retryMsg.includes("already exists")) {
|
|
3562
|
+
return { success: true, message: "Firestore database already exists." };
|
|
3563
|
+
}
|
|
3564
|
+
return { success: false, message: `Failed to create Firestore database after enabling API: ${retryMsg}` };
|
|
3565
|
+
}
|
|
3566
|
+
}
|
|
3435
3567
|
return { success: false, message: `Failed to create Firestore database: ${msg}` };
|
|
3436
3568
|
}
|
|
3437
3569
|
}
|