@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.
Files changed (2) hide show
  1. package/dist/cli/index.js +143 -5
  2. 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
- const entityNames = entities.map((e) => e.name).join(", ");
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.19.f86f4a6",
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": "npm run build && vitest"
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",