@base44-preview/cli 0.0.1-pr.19.f86f4a6 → 0.0.1-pr.20.e0a0f93
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 +143 -5
- package/package.json +2 -8
package/dist/cli/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
-
import { cancel, group, intro, log, select, spinner, text } from "@clack/prompts";
|
|
4
|
+
import { cancel, confirm, group, intro, isCancel, log, select, spinner, text } from "@clack/prompts";
|
|
5
5
|
import pWaitFor from "p-wait-for";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import ky from "ky";
|
|
@@ -688,11 +688,13 @@ async function runCommand(commandFn, options) {
|
|
|
688
688
|
* The spinner is automatically started, and stopped on both success and error.
|
|
689
689
|
*
|
|
690
690
|
* @param startMessage - Message to show when spinner starts
|
|
691
|
-
* @param operation - The async operation to execute
|
|
691
|
+
* @param operation - The async operation to execute. Receives an updateMessage function
|
|
692
|
+
* to update the spinner text during long-running operations.
|
|
692
693
|
* @param options - Optional configuration for success/error messages
|
|
693
694
|
* @returns The result of the operation
|
|
694
695
|
*
|
|
695
696
|
* @example
|
|
697
|
+
* // Simple usage
|
|
696
698
|
* const data = await runTask(
|
|
697
699
|
* "Fetching data...",
|
|
698
700
|
* async () => {
|
|
@@ -704,12 +706,27 @@ async function runCommand(commandFn, options) {
|
|
|
704
706
|
* errorMessage: "Failed to fetch data",
|
|
705
707
|
* }
|
|
706
708
|
* );
|
|
709
|
+
*
|
|
710
|
+
* @example
|
|
711
|
+
* // With progress updates
|
|
712
|
+
* const result = await runTask(
|
|
713
|
+
* "Processing files...",
|
|
714
|
+
* async (updateMessage) => {
|
|
715
|
+
* for (const file of files) {
|
|
716
|
+
* updateMessage(`Processing ${file.name}...`);
|
|
717
|
+
* await process(file);
|
|
718
|
+
* }
|
|
719
|
+
* return files.length;
|
|
720
|
+
* },
|
|
721
|
+
* { successMessage: "All files processed" }
|
|
722
|
+
* );
|
|
707
723
|
*/
|
|
708
724
|
async function runTask(startMessage, operation, options) {
|
|
709
725
|
const s = spinner();
|
|
710
726
|
s.start(startMessage);
|
|
727
|
+
const updateMessage = (message) => s.message(message);
|
|
711
728
|
try {
|
|
712
|
-
const result = await operation();
|
|
729
|
+
const result = await operation(updateMessage);
|
|
713
730
|
s.stop(options?.successMessage || startMessage);
|
|
714
731
|
return result;
|
|
715
732
|
} catch (error) {
|
|
@@ -824,6 +841,102 @@ const showProjectCommand = new Command("show-project").description("Display proj
|
|
|
824
841
|
await runCommand(showProject);
|
|
825
842
|
});
|
|
826
843
|
|
|
844
|
+
//#endregion
|
|
845
|
+
//#region src/core/site/schema.ts
|
|
846
|
+
/**
|
|
847
|
+
* Represents a single file to be deployed.
|
|
848
|
+
* Contains the relative path and base64-encoded content.
|
|
849
|
+
*/
|
|
850
|
+
const SiteFileSchema = z.object({
|
|
851
|
+
path: z.string(),
|
|
852
|
+
content: z.string()
|
|
853
|
+
});
|
|
854
|
+
/**
|
|
855
|
+
* Response from the deploy API endpoint.
|
|
856
|
+
*/
|
|
857
|
+
const DeployResponseSchema = z.object({ url: z.string().url() });
|
|
858
|
+
|
|
859
|
+
//#endregion
|
|
860
|
+
//#region src/core/site/config.ts
|
|
861
|
+
async function readSiteFile(outputDir, relativePath) {
|
|
862
|
+
const content = (await readFile(join(outputDir, relativePath))).toString("base64");
|
|
863
|
+
await new Promise((resolve$1) => setTimeout(resolve$1, 20));
|
|
864
|
+
return {
|
|
865
|
+
path: relativePath,
|
|
866
|
+
content
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
async function getSiteFilePaths(outputDir) {
|
|
870
|
+
return await globby("**/*", {
|
|
871
|
+
cwd: outputDir,
|
|
872
|
+
onlyFiles: true,
|
|
873
|
+
absolute: false
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
/**
|
|
877
|
+
* Reads site files one by one, yielding each file as it's read.
|
|
878
|
+
* Useful for showing progress during file reading.
|
|
879
|
+
*
|
|
880
|
+
* @param outputDir - The directory containing built site files
|
|
881
|
+
* @param filePaths - Array of relative file paths to read
|
|
882
|
+
* @yields Each file as it's read
|
|
883
|
+
*
|
|
884
|
+
* @example
|
|
885
|
+
* const paths = await getSiteFilePaths("./dist");
|
|
886
|
+
* for await (const file of readSiteFilesStream("./dist", paths)) {
|
|
887
|
+
* console.log(`Read: ${file.path}`);
|
|
888
|
+
* }
|
|
889
|
+
*/
|
|
890
|
+
async function* readSiteFilesStream(outputDir, filePaths) {
|
|
891
|
+
for (const relativePath of filePaths) yield await readSiteFile(outputDir, relativePath);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
//#endregion
|
|
895
|
+
//#region src/core/site/api.ts
|
|
896
|
+
/**
|
|
897
|
+
* Uploads site files to the Base44 hosting API.
|
|
898
|
+
*
|
|
899
|
+
* @param files - Array of files with base64-encoded content to upload
|
|
900
|
+
* @returns Deploy response with the site URL
|
|
901
|
+
*/
|
|
902
|
+
async function uploadSite(files) {
|
|
903
|
+
await new Promise((resolve$1) => setTimeout(resolve$1, 2e3));
|
|
904
|
+
return { url: "https://example.base44.app" };
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
//#endregion
|
|
908
|
+
//#region src/core/site/deploy.ts
|
|
909
|
+
/**
|
|
910
|
+
* Deploys a site from the given output directory to Base44 hosting.
|
|
911
|
+
* Reads files one by one with progress callback, validates, and uploads to the API.
|
|
912
|
+
*
|
|
913
|
+
* @param outputDir - The directory containing built site files (e.g., "./dist")
|
|
914
|
+
* @param onProgress - Optional callback called for each file read
|
|
915
|
+
* @returns Deploy response with the site URL
|
|
916
|
+
* @throws Error if no files found in the output directory
|
|
917
|
+
*
|
|
918
|
+
* @example
|
|
919
|
+
* const { url } = await deploySite("./dist", (progress) => {
|
|
920
|
+
* console.log(`Reading ${progress.current}/${progress.total}: ${progress.path}`);
|
|
921
|
+
* });
|
|
922
|
+
*/
|
|
923
|
+
async function deploySite(outputDir, onProgress) {
|
|
924
|
+
const filePaths = await getSiteFilePaths(outputDir);
|
|
925
|
+
if (filePaths.length === 0) throw new Error(`No files found in output directory: ${outputDir}. Make sure to build your project first.`);
|
|
926
|
+
const files = [];
|
|
927
|
+
let current = 0;
|
|
928
|
+
for await (const file of readSiteFilesStream(outputDir, filePaths)) {
|
|
929
|
+
current++;
|
|
930
|
+
onProgress?.({
|
|
931
|
+
total: filePaths.length,
|
|
932
|
+
current,
|
|
933
|
+
path: file.path
|
|
934
|
+
});
|
|
935
|
+
files.push(file);
|
|
936
|
+
}
|
|
937
|
+
return await uploadSite(files);
|
|
938
|
+
}
|
|
939
|
+
|
|
827
940
|
//#endregion
|
|
828
941
|
//#region src/cli/commands/entities/push.ts
|
|
829
942
|
async function pushEntitiesAction() {
|
|
@@ -832,8 +945,7 @@ async function pushEntitiesAction() {
|
|
|
832
945
|
log.warn("No entities found in project");
|
|
833
946
|
return;
|
|
834
947
|
}
|
|
835
|
-
|
|
836
|
-
log.info(`Found ${entities.length} entities to push: ${entityNames}`);
|
|
948
|
+
log.info(`Found ${entities.length} entities to push`);
|
|
837
949
|
const result = await runTask("Pushing entities to Base44", async () => {
|
|
838
950
|
return await pushEntities(entities);
|
|
839
951
|
}, {
|
|
@@ -900,6 +1012,31 @@ const createCommand = new Command("create").description("Create a new Base44 pro
|
|
|
900
1012
|
await runCommand(create, { fullBanner: true });
|
|
901
1013
|
});
|
|
902
1014
|
|
|
1015
|
+
//#endregion
|
|
1016
|
+
//#region src/cli/commands/site/deploy.ts
|
|
1017
|
+
async function deployAction() {
|
|
1018
|
+
const { project } = await readProjectConfig();
|
|
1019
|
+
if (!project.site?.outputDirectory) throw new Error("No site configuration found. Please add 'site.outputDirectory' to your config.jsonc");
|
|
1020
|
+
const outputDir = resolve(project.root, project.site.outputDirectory);
|
|
1021
|
+
const shouldDeploy = await confirm({ message: `Deploy site from ${project.site.outputDirectory}?` });
|
|
1022
|
+
if (isCancel(shouldDeploy) || !shouldDeploy) {
|
|
1023
|
+
log.warn("Deployment cancelled");
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
const result = await runTask("Reading site files...", async (updateMessage) => {
|
|
1027
|
+
return await deploySite(outputDir, (progress) => {
|
|
1028
|
+
updateMessage(`Reading files (${progress.current}/${progress.total}): ${progress.path}`);
|
|
1029
|
+
});
|
|
1030
|
+
}, {
|
|
1031
|
+
successMessage: "Site deployed successfully",
|
|
1032
|
+
errorMessage: "Deployment failed"
|
|
1033
|
+
});
|
|
1034
|
+
log.success(`Site deployed to: ${result.url}`);
|
|
1035
|
+
}
|
|
1036
|
+
const siteDeployCommand = new Command("site").description("Manage site deployments").addCommand(new Command("deploy").description("Deploy built site files to Base44 hosting").action(async () => {
|
|
1037
|
+
await runCommand(deployAction);
|
|
1038
|
+
}));
|
|
1039
|
+
|
|
903
1040
|
//#endregion
|
|
904
1041
|
//#region package.json
|
|
905
1042
|
var version = "0.0.1";
|
|
@@ -914,6 +1051,7 @@ program.addCommand(logoutCommand);
|
|
|
914
1051
|
program.addCommand(createCommand);
|
|
915
1052
|
program.addCommand(showProjectCommand);
|
|
916
1053
|
program.addCommand(entitiesPushCommand);
|
|
1054
|
+
program.addCommand(siteDeployCommand);
|
|
917
1055
|
program.parse();
|
|
918
1056
|
|
|
919
1057
|
//#endregion
|
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.20.e0a0f93",
|
|
4
4
|
"description": "Base44 CLI - Unified interface for managing Base44 applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli/index.js",
|
|
@@ -18,9 +18,8 @@
|
|
|
18
18
|
"start": "node dist/cli/index.js",
|
|
19
19
|
"clean": "rm -rf dist",
|
|
20
20
|
"lint": "eslint src",
|
|
21
|
-
"pretest": "npm run build",
|
|
22
21
|
"test": "vitest run",
|
|
23
|
-
"test:watch": "
|
|
22
|
+
"test:watch": "vitest"
|
|
24
23
|
},
|
|
25
24
|
"keywords": [
|
|
26
25
|
"base44",
|
|
@@ -51,16 +50,11 @@
|
|
|
51
50
|
"@types/ejs": "^3.1.5",
|
|
52
51
|
"@types/lodash.kebabcase": "^4.1.9",
|
|
53
52
|
"@types/node": "^22.10.5",
|
|
54
|
-
"@types/polka": "^0.5.8",
|
|
55
53
|
"@typescript-eslint/eslint-plugin": "^8.51.0",
|
|
56
54
|
"@typescript-eslint/parser": "^8.51.0",
|
|
57
55
|
"eslint": "^9.39.2",
|
|
58
56
|
"eslint-plugin-import": "^2.32.0",
|
|
59
57
|
"eslint-plugin-unicorn": "^62.0.0",
|
|
60
|
-
"execa": "^9.6.1",
|
|
61
|
-
"polka": "^0.5.2",
|
|
62
|
-
"strip-ansi": "^7.1.2",
|
|
63
|
-
"tmp-promise": "^3.0.3",
|
|
64
58
|
"tsdown": "^0.12.4",
|
|
65
59
|
"tsx": "^4.19.2",
|
|
66
60
|
"typescript": "^5.7.2",
|