@base44-preview/cli 0.0.1-pr.14.987d307 → 0.0.1-pr.15.8b10ac1
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/index.js
CHANGED
|
@@ -1,36 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
-
import {
|
|
4
|
+
import { intro, log, spinner } from "@clack/prompts";
|
|
5
5
|
import pWaitFor from "p-wait-for";
|
|
6
6
|
import { z } from "zod";
|
|
7
|
-
import { dirname, join
|
|
7
|
+
import { dirname, join } from "node:path";
|
|
8
8
|
import { homedir } from "node:os";
|
|
9
|
-
import { config } from "dotenv";
|
|
10
9
|
import ky from "ky";
|
|
11
10
|
import { access, mkdir, readFile, unlink, writeFile } from "node:fs/promises";
|
|
12
11
|
import { parse, printParseErrorCode } from "jsonc-parser";
|
|
13
12
|
import { globby } from "globby";
|
|
14
|
-
import { fileURLToPath } from "node:url";
|
|
15
|
-
import ejs from "ejs";
|
|
16
13
|
|
|
17
|
-
//#region rolldown:runtime
|
|
18
|
-
var __defProp = Object.defineProperty;
|
|
19
|
-
var __exportAll = (all, symbols) => {
|
|
20
|
-
let target = {};
|
|
21
|
-
for (var name in all) {
|
|
22
|
-
__defProp(target, name, {
|
|
23
|
-
get: all[name],
|
|
24
|
-
enumerable: true
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
if (symbols) {
|
|
28
|
-
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
29
|
-
}
|
|
30
|
-
return target;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
//#endregion
|
|
34
14
|
//#region src/core/auth/schema.ts
|
|
35
15
|
const AuthDataSchema = z.object({
|
|
36
16
|
accessToken: z.string().min(1, "Token cannot be empty"),
|
|
@@ -93,11 +73,9 @@ var AuthValidationError = class extends Error {
|
|
|
93
73
|
};
|
|
94
74
|
|
|
95
75
|
//#endregion
|
|
96
|
-
//#region src/core/
|
|
76
|
+
//#region src/core/consts.ts
|
|
97
77
|
const PROJECT_SUBDIR = "base44";
|
|
98
78
|
const FUNCTION_CONFIG_FILE = "function.jsonc";
|
|
99
|
-
const AUTH_CLIENT_ID = "base44_cli";
|
|
100
|
-
const DEFAULT_API_URL = "https://app.base44.com";
|
|
101
79
|
function getBase44Dir() {
|
|
102
80
|
return join(homedir(), ".base44");
|
|
103
81
|
}
|
|
@@ -112,34 +90,15 @@ function getProjectConfigPatterns() {
|
|
|
112
90
|
"config.json"
|
|
113
91
|
];
|
|
114
92
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
* Values won't override existing process.env variables.
|
|
118
|
-
* Safe to call multiple times - only loads once.
|
|
119
|
-
*/
|
|
120
|
-
async function loadProjectEnv(projectRoot) {
|
|
121
|
-
const { findProjectRoot: findProjectRoot$1 } = await Promise.resolve().then(() => config_exports);
|
|
122
|
-
const found = projectRoot ? { root: projectRoot } : await findProjectRoot$1();
|
|
123
|
-
if (!found) return;
|
|
124
|
-
config({
|
|
125
|
-
path: join(found.root, ".env.local"),
|
|
126
|
-
override: false
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Get the Base44 API URL.
|
|
131
|
-
* Priority: process.env.BASE44_API_URL > .env.local > default
|
|
132
|
-
*/
|
|
93
|
+
const AUTH_CLIENT_ID = "base44_cli";
|
|
94
|
+
const DEFAULT_API_URL = "https://app.base44.com";
|
|
133
95
|
function getBase44ApiUrl() {
|
|
134
96
|
return process.env.BASE44_API_URL || DEFAULT_API_URL;
|
|
135
97
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
*/
|
|
141
|
-
function getBase44ClientId() {
|
|
142
|
-
return process.env.BASE44_CLIENT_ID;
|
|
98
|
+
function getAppId() {
|
|
99
|
+
const appId = process.env.BASE44_CLIENT_ID;
|
|
100
|
+
if (!appId) throw new Error("BASE44_CLIENT_ID environment variable is not set");
|
|
101
|
+
return appId;
|
|
143
102
|
}
|
|
144
103
|
|
|
145
104
|
//#endregion
|
|
@@ -222,18 +181,8 @@ async function getUserInfo(accessToken) {
|
|
|
222
181
|
|
|
223
182
|
//#endregion
|
|
224
183
|
//#region src/core/utils/fs.ts
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
await access(path);
|
|
228
|
-
return true;
|
|
229
|
-
} catch {
|
|
230
|
-
return false;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
async function writeFile$1(filePath, content) {
|
|
234
|
-
const dir = dirname(filePath);
|
|
235
|
-
if (!await pathExists(dir)) await mkdir(dir, { recursive: true });
|
|
236
|
-
await writeFile(filePath, content, "utf-8");
|
|
184
|
+
function pathExists(path) {
|
|
185
|
+
return access(path).then(() => true).catch(() => false);
|
|
237
186
|
}
|
|
238
187
|
async function readJsonFile(filePath) {
|
|
239
188
|
if (!await pathExists(filePath)) throw new Error(`File not found: ${filePath}`);
|
|
@@ -252,13 +201,21 @@ async function readJsonFile(filePath) {
|
|
|
252
201
|
}
|
|
253
202
|
}
|
|
254
203
|
async function writeJsonFile(filePath, data) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
204
|
+
try {
|
|
205
|
+
const dir = dirname(filePath);
|
|
206
|
+
if (!await pathExists(dir)) await mkdir(dir, { recursive: true });
|
|
207
|
+
await writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
208
|
+
} catch (error) {
|
|
209
|
+
throw new Error(`Failed to write file ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
210
|
+
}
|
|
258
211
|
}
|
|
259
212
|
async function deleteFile(filePath) {
|
|
260
213
|
if (!await pathExists(filePath)) return;
|
|
261
|
-
|
|
214
|
+
try {
|
|
215
|
+
await unlink(filePath);
|
|
216
|
+
} catch (error) {
|
|
217
|
+
throw new Error(`Failed to delete file ${filePath}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
218
|
+
}
|
|
262
219
|
}
|
|
263
220
|
|
|
264
221
|
//#endregion
|
|
@@ -333,13 +290,11 @@ const base44Color = chalk.bgHex("#E86B3C");
|
|
|
333
290
|
/**
|
|
334
291
|
* Wraps a command function with the Base44 intro banner.
|
|
335
292
|
* All CLI commands should use this utility to ensure consistent branding.
|
|
336
|
-
* Also loads .env.local from the project root if available.
|
|
337
293
|
*
|
|
338
294
|
* @param commandFn - The async function to execute as the command
|
|
339
295
|
*/
|
|
340
296
|
async function runCommand(commandFn) {
|
|
341
297
|
intro(base44Color(" Base 44 "));
|
|
342
|
-
await loadProjectEnv();
|
|
343
298
|
try {
|
|
344
299
|
await commandFn();
|
|
345
300
|
} catch (e) {
|
|
@@ -373,42 +328,6 @@ async function runTask(startMessage, operation, options) {
|
|
|
373
328
|
}
|
|
374
329
|
}
|
|
375
330
|
|
|
376
|
-
//#endregion
|
|
377
|
-
//#region src/cli/utils/prompts.ts
|
|
378
|
-
/**
|
|
379
|
-
* Handles prompt cancellation by exiting gracefully.
|
|
380
|
-
*/
|
|
381
|
-
function handleCancel(value) {
|
|
382
|
-
if (isCancel(value)) {
|
|
383
|
-
cancel("Operation cancelled.");
|
|
384
|
-
process.exit(0);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
/**
|
|
388
|
-
* Wrapper around @clack/prompts text() that handles cancellation automatically.
|
|
389
|
-
* Returns the string value directly, exits process if cancelled.
|
|
390
|
-
*/
|
|
391
|
-
async function textPrompt(options) {
|
|
392
|
-
const value = await text(options);
|
|
393
|
-
handleCancel(value);
|
|
394
|
-
return value;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
//#endregion
|
|
398
|
-
//#region src/cli/utils/banner.ts
|
|
399
|
-
const orange = chalk.hex("#E86B3C");
|
|
400
|
-
const BANNER = `
|
|
401
|
-
${orange("██████╗ █████╗ ███████╗███████╗ ██╗ ██╗██╗ ██╗")}
|
|
402
|
-
${orange("██╔══██╗██╔══██╗██╔════╝██╔════╝ ██║ ██║██║ ██║")}
|
|
403
|
-
${orange("██████╔╝███████║███████╗█████╗ ███████║███████║")}
|
|
404
|
-
${orange("██╔══██╗██╔══██║╚════██║██╔══╝ ╚════██║╚════██║")}
|
|
405
|
-
${orange("██████╔╝██║ ██║███████║███████╗ ██║ ██║")}
|
|
406
|
-
${orange("╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝ ╚═╝ ╚═╝")}
|
|
407
|
-
`;
|
|
408
|
-
function printBanner() {
|
|
409
|
-
console.log(BANNER);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
331
|
//#endregion
|
|
413
332
|
//#region src/cli/commands/auth/login.ts
|
|
414
333
|
async function generateAndDisplayDeviceCode() {
|
|
@@ -581,7 +500,7 @@ const base44Client = ky.create({
|
|
|
581
500
|
* Returns an HTTP client scoped to the current app.
|
|
582
501
|
*/
|
|
583
502
|
function getAppClient() {
|
|
584
|
-
return base44Client.extend({ prefixUrl: new URL(`/api/apps/${
|
|
503
|
+
return base44Client.extend({ prefixUrl: new URL(`/api/apps/${getAppId()}/`, getBase44ApiUrl()).href });
|
|
585
504
|
}
|
|
586
505
|
|
|
587
506
|
//#endregion
|
|
@@ -668,11 +587,6 @@ const functionResource = { readAll: readAllFunctions };
|
|
|
668
587
|
|
|
669
588
|
//#endregion
|
|
670
589
|
//#region src/core/project/config.ts
|
|
671
|
-
var config_exports = /* @__PURE__ */ __exportAll({
|
|
672
|
-
ProjectConfigSchema: () => ProjectConfigSchema,
|
|
673
|
-
findProjectRoot: () => findProjectRoot,
|
|
674
|
-
readProjectConfig: () => readProjectConfig
|
|
675
|
-
});
|
|
676
590
|
const ProjectConfigSchema = z.looseObject({
|
|
677
591
|
name: z.string().min(1, "Project name cannot be empty"),
|
|
678
592
|
entitiesDir: z.string().default("./entities"),
|
|
@@ -757,60 +671,6 @@ const AppConfigSchema = z.object({
|
|
|
757
671
|
site: SiteConfigSchema.optional(),
|
|
758
672
|
domains: z.array(z.string()).optional()
|
|
759
673
|
});
|
|
760
|
-
const CreateProjectResponseSchema = z.looseObject({ id: z.string() });
|
|
761
|
-
|
|
762
|
-
//#endregion
|
|
763
|
-
//#region src/core/project/api.ts
|
|
764
|
-
async function createProject(projectName, description) {
|
|
765
|
-
const response = await base44Client.post("api/apps", { json: {
|
|
766
|
-
name: projectName,
|
|
767
|
-
user_description: description ?? `Backend for '${projectName}'`,
|
|
768
|
-
app_type: "baas"
|
|
769
|
-
} });
|
|
770
|
-
return { projectId: CreateProjectResponseSchema.parse(await response.json()).id };
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
//#endregion
|
|
774
|
-
//#region src/core/project/templates/index.ts
|
|
775
|
-
const TEMPLATES_DIR = join(dirname(fileURLToPath(import.meta.url)), "templates");
|
|
776
|
-
const CONFIG_TEMPLATE_PATH = join(TEMPLATES_DIR, "config.jsonc.ejs");
|
|
777
|
-
const ENV_TEMPLATE_PATH = join(TEMPLATES_DIR, "env.local.ejs");
|
|
778
|
-
async function renderConfigTemplate(data) {
|
|
779
|
-
return ejs.renderFile(CONFIG_TEMPLATE_PATH, data);
|
|
780
|
-
}
|
|
781
|
-
async function renderEnvTemplate(data) {
|
|
782
|
-
return ejs.renderFile(ENV_TEMPLATE_PATH, data);
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
//#endregion
|
|
786
|
-
//#region src/core/project/init.ts
|
|
787
|
-
/**
|
|
788
|
-
* Initialize a new Base44 project.
|
|
789
|
-
* Creates the base44 directory, config.jsonc, and .env.local files.
|
|
790
|
-
*/
|
|
791
|
-
async function initProject(options) {
|
|
792
|
-
const { name, description, path: basePath } = options;
|
|
793
|
-
const projectDir = join(basePath, PROJECT_SUBDIR);
|
|
794
|
-
const configPath = join(projectDir, "config.jsonc");
|
|
795
|
-
const envPath = join(projectDir, ".env.local");
|
|
796
|
-
const existingConfigs = await globby(getProjectConfigPatterns(), {
|
|
797
|
-
cwd: basePath,
|
|
798
|
-
absolute: true
|
|
799
|
-
});
|
|
800
|
-
if (existingConfigs.length > 0) throw new Error(`A Base44 project already exists at ${existingConfigs[0]}. Please choose a different location.`);
|
|
801
|
-
const { projectId } = await createProject(name, description);
|
|
802
|
-
await writeFile$1(configPath, await renderConfigTemplate({
|
|
803
|
-
name,
|
|
804
|
-
description
|
|
805
|
-
}));
|
|
806
|
-
await writeFile$1(envPath, await renderEnvTemplate({ projectId }));
|
|
807
|
-
return {
|
|
808
|
-
projectId,
|
|
809
|
-
projectDir,
|
|
810
|
-
configPath,
|
|
811
|
-
envPath
|
|
812
|
-
};
|
|
813
|
-
}
|
|
814
674
|
|
|
815
675
|
//#endregion
|
|
816
676
|
//#region src/cli/commands/entities/push.ts
|
|
@@ -836,50 +696,6 @@ const entitiesPushCommand = new Command("entities").description("Manage project
|
|
|
836
696
|
await runCommand(pushEntitiesAction);
|
|
837
697
|
}));
|
|
838
698
|
|
|
839
|
-
//#endregion
|
|
840
|
-
//#region src/cli/commands/project/init.ts
|
|
841
|
-
async function init() {
|
|
842
|
-
printBanner();
|
|
843
|
-
await loadProjectEnv();
|
|
844
|
-
const name = await textPrompt({
|
|
845
|
-
message: "What is the name of your project?",
|
|
846
|
-
placeholder: "my-app-backend",
|
|
847
|
-
validate: (value) => {
|
|
848
|
-
if (!value || value.trim().length === 0) return "Project name is required";
|
|
849
|
-
}
|
|
850
|
-
});
|
|
851
|
-
const description = await textPrompt({
|
|
852
|
-
message: "Project description (optional)",
|
|
853
|
-
placeholder: "A brief description of your project"
|
|
854
|
-
});
|
|
855
|
-
const defaultPath = "./";
|
|
856
|
-
const resolvedPath = resolve(await textPrompt({
|
|
857
|
-
message: "Where should we create the base44 folder?",
|
|
858
|
-
placeholder: defaultPath,
|
|
859
|
-
initialValue: defaultPath
|
|
860
|
-
}) || defaultPath);
|
|
861
|
-
await runTask("Creating project...", async () => {
|
|
862
|
-
return await initProject({
|
|
863
|
-
name: name.trim(),
|
|
864
|
-
description: description ? description.trim() : void 0,
|
|
865
|
-
path: resolvedPath
|
|
866
|
-
});
|
|
867
|
-
}, {
|
|
868
|
-
successMessage: "Project created successfully",
|
|
869
|
-
errorMessage: "Failed to create project"
|
|
870
|
-
});
|
|
871
|
-
log.success(`Project ${chalk.bold(name)} has been initialized!`);
|
|
872
|
-
}
|
|
873
|
-
const initCommand = new Command("init").alias("create").description("Initialize a new Base44 project").action(async () => {
|
|
874
|
-
try {
|
|
875
|
-
await init();
|
|
876
|
-
} catch (e) {
|
|
877
|
-
if (e instanceof Error) log.error(e.stack ?? e.message);
|
|
878
|
-
else log.error(String(e));
|
|
879
|
-
process.exit(1);
|
|
880
|
-
}
|
|
881
|
-
});
|
|
882
|
-
|
|
883
699
|
//#endregion
|
|
884
700
|
//#region package.json
|
|
885
701
|
var version = "0.0.1";
|
|
@@ -891,10 +707,9 @@ program.name("base44").description("Base44 CLI - Unified interface for managing
|
|
|
891
707
|
program.addCommand(loginCommand);
|
|
892
708
|
program.addCommand(whoamiCommand);
|
|
893
709
|
program.addCommand(logoutCommand);
|
|
894
|
-
program.addCommand(initCommand);
|
|
895
710
|
program.addCommand(showProjectCommand);
|
|
896
711
|
program.addCommand(entitiesPushCommand);
|
|
897
712
|
program.parse();
|
|
898
713
|
|
|
899
714
|
//#endregion
|
|
900
|
-
export {
|
|
715
|
+
export { };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@base44-preview/cli",
|
|
3
|
-
"version": "0.0.1-pr.
|
|
3
|
+
"version": "0.0.1-pr.15.8b10ac1",
|
|
4
4
|
"description": "Base44 CLI - Unified interface for managing Base44 applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli/index.js",
|
|
@@ -36,8 +36,6 @@
|
|
|
36
36
|
"@clack/prompts": "^0.11.0",
|
|
37
37
|
"chalk": "^5.6.2",
|
|
38
38
|
"commander": "^12.1.0",
|
|
39
|
-
"dotenv": "^17.2.3",
|
|
40
|
-
"ejs": "^3.1.10",
|
|
41
39
|
"globby": "^16.1.0",
|
|
42
40
|
"jsonc-parser": "^3.3.1",
|
|
43
41
|
"ky": "^1.14.2",
|
|
@@ -46,7 +44,6 @@
|
|
|
46
44
|
},
|
|
47
45
|
"devDependencies": {
|
|
48
46
|
"@stylistic/eslint-plugin": "^5.6.1",
|
|
49
|
-
"@types/ejs": "^3.1.5",
|
|
50
47
|
"@types/node": "^22.10.5",
|
|
51
48
|
"@typescript-eslint/eslint-plugin": "^8.51.0",
|
|
52
49
|
"@typescript-eslint/parser": "^8.51.0",
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// Base44 Project Configuration
|
|
2
|
-
// JSONC enables inline documentation and discoverability directly in config files.
|
|
3
|
-
// Commented-out properties show available options you can enable.
|
|
4
|
-
|
|
5
|
-
{
|
|
6
|
-
"name": "<%= name %>"<% if (description) { %>,
|
|
7
|
-
"description": "<%= description %>"<% } %>
|
|
8
|
-
|
|
9
|
-
// Site/hosting configuration
|
|
10
|
-
// Docs: https://docs.base44.com/configuration/hosting
|
|
11
|
-
// "site": {
|
|
12
|
-
// "buildCommand": "npm run build",
|
|
13
|
-
// "serveCommand": "npm run dev",
|
|
14
|
-
// "outputDirectory": "./dist",
|
|
15
|
-
// "installCommand": "npm ci"
|
|
16
|
-
// }
|
|
17
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { dirname, join } from "node:path";
|
|
2
|
-
import { fileURLToPath } from "node:url";
|
|
3
|
-
import ejs from "ejs";
|
|
4
|
-
|
|
5
|
-
// After bundling, import.meta.url points to dist/cli/index.js
|
|
6
|
-
// Templates are copied to dist/cli/templates/
|
|
7
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const TEMPLATES_DIR = join(__dirname, "templates");
|
|
9
|
-
|
|
10
|
-
const CONFIG_TEMPLATE_PATH = join(TEMPLATES_DIR, "config.jsonc.ejs");
|
|
11
|
-
const ENV_TEMPLATE_PATH = join(TEMPLATES_DIR, "env.local.ejs");
|
|
12
|
-
|
|
13
|
-
interface ConfigTemplateData {
|
|
14
|
-
name: string;
|
|
15
|
-
description?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface EnvTemplateData {
|
|
19
|
-
projectId: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export async function renderConfigTemplate(
|
|
23
|
-
data: ConfigTemplateData
|
|
24
|
-
): Promise<string> {
|
|
25
|
-
return ejs.renderFile(CONFIG_TEMPLATE_PATH, data);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export async function renderEnvTemplate(data: EnvTemplateData): Promise<string> {
|
|
29
|
-
return ejs.renderFile(ENV_TEMPLATE_PATH, data);
|
|
30
|
-
}
|