@base44-preview/cli 0.0.50-pr.471.086f7c9 → 0.0.50-pr.475.9d797d7

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
@@ -219926,7 +219926,8 @@ var theme = {
219926
219926
  bold: source_default.bold,
219927
219927
  dim: source_default.dim,
219928
219928
  error: source_default.red,
219929
- warn: source_default.yellow
219929
+ warn: source_default.yellow,
219930
+ info: source_default.cyan
219930
219931
  },
219931
219932
  format: {
219932
219933
  errorContext(ctx) {
@@ -242594,27 +242595,11 @@ var EntityAutomationSchema = AutomationBaseSchema.extend({
242594
242595
  entity_name: exports_external.string().min(1, "Entity name cannot be empty"),
242595
242596
  event_types: exports_external.array(exports_external.enum(["create", "update", "delete"])).min(1, "At least one event type is required")
242596
242597
  });
242597
- var TriggerConditionSchema = exports_external.object({
242598
- field: exports_external.string().min(1),
242599
- operator: exports_external.string().min(1),
242600
- value: exports_external.unknown()
242601
- });
242602
- var TriggerConditionsSchema = exports_external.object({
242603
- conditions: exports_external.array(TriggerConditionSchema).min(1)
242604
- });
242605
- var ConnectorAutomationSchema = AutomationBaseSchema.extend({
242606
- type: exports_external.literal("connector"),
242607
- integration_type: exports_external.string().min(1, "Integration type cannot be empty"),
242608
- events: exports_external.array(exports_external.string()).min(1, "At least one event is required"),
242609
- resource_id: exports_external.string().nullable().optional(),
242610
- trigger_conditions: TriggerConditionsSchema.nullable().optional()
242611
- });
242612
242598
  var AutomationSchema = exports_external.union([
242613
242599
  ScheduledOneTimeSchema,
242614
242600
  ScheduledCronSchema,
242615
242601
  ScheduledSimpleSchema,
242616
- EntityAutomationSchema,
242617
- ConnectorAutomationSchema
242602
+ EntityAutomationSchema
242618
242603
  ]);
242619
242604
  var FunctionConfigSchema = exports_external.object({
242620
242605
  name: FunctionNameSchema,
@@ -252771,9 +252756,12 @@ function getTypesCommand() {
252771
252756
  return new Command("types").description("Manage TypeScript type generation").addCommand(getTypesGenerateCommand());
252772
252757
  }
252773
252758
 
252759
+ // src/cli/commands/dev.ts
252760
+ import process21 from "node:process";
252761
+
252774
252762
  // src/cli/dev/dev-server/main.ts
252775
252763
  var import_cors = __toESM(require_lib4(), 1);
252776
- var import_express5 = __toESM(require_express(), 1);
252764
+ var import_express6 = __toESM(require_express(), 1);
252777
252765
  import { dirname as dirname16, join as join23 } from "node:path";
252778
252766
 
252779
252767
  // ../../node_modules/get-port/index.js
@@ -253459,15 +253447,200 @@ function broadcastEntityEvent(io6, appId, entityName, event) {
253459
253447
  });
253460
253448
  }
253461
253449
 
253462
- // src/cli/dev/dev-server/routes/entities/entities-router.ts
253463
- var import_express3 = __toESM(require_express(), 1);
253464
-
253465
- // src/cli/dev/dev-server/routes/entities/entities-user-router.ts
253450
+ // src/cli/dev/dev-server/routes/auth-router.ts
253466
253451
  var import_express2 = __toESM(require_express(), 1);
253467
253452
  var import_jsonwebtoken = __toESM(require_jsonwebtoken(), 1);
253468
- function createUserRouter(db2, logger2) {
253453
+ import { randomInt } from "node:crypto";
253454
+ var LOCAL_DEV_SECRET = "LOCAL_DEV_SECRET";
253455
+ var generateCode = () => {
253456
+ return randomInt(1e5, 1e6).toString();
253457
+ };
253458
+ var createJwtToken = (email3) => {
253459
+ return import_jsonwebtoken.default.sign({ sub: email3 }, LOCAL_DEV_SECRET, {
253460
+ expiresIn: "360d"
253461
+ });
253462
+ };
253463
+ var UserRegiterSchema = object({
253464
+ id: string2(),
253465
+ email: email2(),
253466
+ otpCode: string2().length(6),
253467
+ password: string2().min(8),
253468
+ createdAt: number2().min(1)
253469
+ });
253470
+ function createAuthRouter(db2, logger2) {
253469
253471
  const router = import_express2.Router({ mergeParams: true });
253472
+ const userRegitrPendingMap = new Map;
253470
253473
  const parseBody = import_express2.json();
253474
+ router.post("/login", parseBody, async (req, res) => {
253475
+ const { email: email3, password: _password } = req.body;
253476
+ const result = await db2.getCollection(USER_COLLECTION)?.findOneAsync({ email: email3 });
253477
+ if (result) {
253478
+ res.json({
253479
+ access_token: createJwtToken(email3),
253480
+ success: true,
253481
+ user: {}
253482
+ });
253483
+ return;
253484
+ }
253485
+ res.status(401).json({ error: "Unauthorized" });
253486
+ });
253487
+ router.post("/register", parseBody, async (req, res) => {
253488
+ const { email: email3, password } = req.body;
253489
+ if ((password || "").length < 8) {
253490
+ res.status(400).json({
253491
+ detail: "Password must be at least 8 characters long",
253492
+ error_type: "HTTPException",
253493
+ message: "Password must be at least 8 characters long",
253494
+ request_id: null,
253495
+ traceback: ""
253496
+ });
253497
+ return;
253498
+ }
253499
+ const result = await db2.getCollection(USER_COLLECTION)?.findOneAsync({ email: email3 });
253500
+ if (result) {
253501
+ res.status(400).json({
253502
+ detail: "A user with this email already exists",
253503
+ error_type: "HTTPException",
253504
+ message: "A user with this email already exists",
253505
+ request_id: null,
253506
+ traceback: ""
253507
+ });
253508
+ return;
253509
+ }
253510
+ const otpCode = generateCode();
253511
+ const id2 = nanoid3();
253512
+ userRegitrPendingMap.set(email3, {
253513
+ id: id2,
253514
+ email: email3,
253515
+ otpCode,
253516
+ password,
253517
+ createdAt: +Date.now()
253518
+ });
253519
+ logger2.log(theme.styles.info(`
253520
+ In order to complete registration use this verification code: ${otpCode}
253521
+ `));
253522
+ res.json({
253523
+ id: id2,
253524
+ message: "Registration successful. Please check your email for the verification code.",
253525
+ otp_expires_in_minutes: 10
253526
+ });
253527
+ });
253528
+ router.post("/verify-otp", parseBody, async (req, res) => {
253529
+ const { email: email3, otp_code } = req.body;
253530
+ const userData = userRegitrPendingMap.get(email3);
253531
+ if (userData && userData.otpCode === otp_code) {
253532
+ if (+Date.now() - userData.createdAt < 10 * 60 * 1000) {
253533
+ const collection = db2.getCollection(USER_COLLECTION);
253534
+ const now = getNowISOTimestamp();
253535
+ const nameFromEmailMatch = /^([^@]+)/.exec(email3);
253536
+ const fullName = nameFromEmailMatch ? nameFromEmailMatch[1] : email3;
253537
+ await collection?.insertAsync({
253538
+ id: userData.id,
253539
+ email: email3,
253540
+ full_name: fullName,
253541
+ is_service: false,
253542
+ is_verified: true,
253543
+ disabled: null,
253544
+ role: "user",
253545
+ collaborator_role: "editor",
253546
+ created_date: now,
253547
+ updated_date: now
253548
+ });
253549
+ res.json({
253550
+ id: userData.id,
253551
+ access_token: createJwtToken(email3),
253552
+ message: "Email verified successfully. You are now logged in.",
253553
+ success: true
253554
+ });
253555
+ } else {
253556
+ res.status(400).json({
253557
+ detail: "Verification code has expired",
253558
+ error_type: "HTTPException",
253559
+ message: "Verification code has expired",
253560
+ request_id: null,
253561
+ traceback: ""
253562
+ });
253563
+ }
253564
+ } else {
253565
+ const appId = req.params.appId;
253566
+ res.status(500).json({
253567
+ detail: `{'email': '${email3}', 'app_id': '${appId}}'} -> Object not found`,
253568
+ error_type: "ObjectNotFoundError",
253569
+ message: `{'email': '${email3}', 'app_id': '${appId}}'} -> Object not found`,
253570
+ request_id: null,
253571
+ traceback: ""
253572
+ });
253573
+ }
253574
+ });
253575
+ return router;
253576
+ }
253577
+
253578
+ // src/cli/dev/dev-server/routes/entities/entities-router.ts
253579
+ var import_express4 = __toESM(require_express(), 1);
253580
+
253581
+ // src/cli/dev/dev-server/db/entity-queries.ts
253582
+ function parseSort(sort) {
253583
+ if (!sort) {
253584
+ return;
253585
+ }
253586
+ if (sort.startsWith("-")) {
253587
+ return { [sort.slice(1)]: -1 };
253588
+ }
253589
+ return { [sort]: 1 };
253590
+ }
253591
+ function parseFields(fields) {
253592
+ if (!fields) {
253593
+ return;
253594
+ }
253595
+ const projection = {};
253596
+ for (const field of fields.split(",")) {
253597
+ const trimmed = field.trim();
253598
+ if (trimmed) {
253599
+ projection[trimmed] = 1;
253600
+ }
253601
+ }
253602
+ return Object.keys(projection).length > 0 ? projection : undefined;
253603
+ }
253604
+ var queryEntity = async (collection, reqQuery) => {
253605
+ const { sort, limit, skip: skip2, fields, q: q13 } = reqQuery;
253606
+ let query = {};
253607
+ if (q13 && typeof q13 === "string") {
253608
+ try {
253609
+ query = JSON.parse(q13);
253610
+ } catch {
253611
+ throw new InvalidInputError("Invalid query parameter 'q'");
253612
+ }
253613
+ }
253614
+ let cursor3 = collection.findAsync(query);
253615
+ const sortObj = parseSort(sort);
253616
+ if (sortObj) {
253617
+ cursor3 = cursor3.sort(sortObj);
253618
+ }
253619
+ if (skip2) {
253620
+ const skipNum = Number.parseInt(skip2, 10);
253621
+ if (!Number.isNaN(skipNum)) {
253622
+ cursor3 = cursor3.skip(skipNum);
253623
+ }
253624
+ }
253625
+ if (limit) {
253626
+ const limitNum = Number.parseInt(limit, 10);
253627
+ if (!Number.isNaN(limitNum)) {
253628
+ cursor3 = cursor3.limit(limitNum);
253629
+ }
253630
+ }
253631
+ const projection = parseFields(fields);
253632
+ if (projection) {
253633
+ cursor3 = cursor3.projection(projection);
253634
+ }
253635
+ return cursor3;
253636
+ };
253637
+
253638
+ // src/cli/dev/dev-server/routes/entities/entities-user-router.ts
253639
+ var import_express3 = __toESM(require_express(), 1);
253640
+ var import_jsonwebtoken2 = __toESM(require_jsonwebtoken(), 1);
253641
+ function createUserRouter(db2, logger2) {
253642
+ const router = import_express3.Router({ mergeParams: true });
253643
+ const parseBody = import_express3.json();
253471
253644
  function withAuth(handler) {
253472
253645
  return async (req, res) => {
253473
253646
  const auth2 = req.headers.authorization;
@@ -253476,7 +253649,7 @@ function createUserRouter(db2, logger2) {
253476
253649
  return;
253477
253650
  }
253478
253651
  try {
253479
- const { payload } = import_jsonwebtoken.default.decode(auth2.replace("Bearer ", ""), { complete: true }) ?? {};
253652
+ const { payload } = import_jsonwebtoken2.default.decode(auth2.replace("Bearer ", ""), { complete: true }) ?? {};
253480
253653
  const result = await db2.getCollection(USER_COLLECTION)?.findOneAsync({ email: payload?.sub });
253481
253654
  if (!result) {
253482
253655
  res.status(404).json({ error: "Unable to read data for the current user" });
@@ -253509,6 +253682,28 @@ function createUserRouter(db2, logger2) {
253509
253682
  ...req.body
253510
253683
  });
253511
253684
  }));
253685
+ router.get("/", withAuth(async (req, res, currentUser) => {
253686
+ const collection = db2.getCollection(USER_COLLECTION);
253687
+ if (!collection) {
253688
+ res.status(404).json({ error: `Entity "${USER_COLLECTION}" not found` });
253689
+ return;
253690
+ }
253691
+ try {
253692
+ if (currentUser.role === "admin") {
253693
+ const result = await queryEntity(collection, req.query);
253694
+ res.json(stripInternalFields(result));
253695
+ } else {
253696
+ res.json([stripInternalFields(currentUser)]);
253697
+ }
253698
+ } catch (error48) {
253699
+ if (error48 instanceof InvalidInputError) {
253700
+ res.status(400).json({ error: error48.message });
253701
+ } else {
253702
+ logger2.error(`Error in GET /${USER_COLLECTION}:`, error48);
253703
+ res.status(500).json({ error: "Internal server error" });
253704
+ }
253705
+ }
253706
+ }));
253512
253707
  router.post("/bulk", async (_req, res) => {
253513
253708
  res.json({});
253514
253709
  });
@@ -253558,31 +253753,9 @@ function createUserRouter(db2, logger2) {
253558
253753
  }
253559
253754
 
253560
253755
  // src/cli/dev/dev-server/routes/entities/entities-router.ts
253561
- function parseSort(sort) {
253562
- if (!sort) {
253563
- return;
253564
- }
253565
- if (sort.startsWith("-")) {
253566
- return { [sort.slice(1)]: -1 };
253567
- }
253568
- return { [sort]: 1 };
253569
- }
253570
- function parseFields(fields) {
253571
- if (!fields) {
253572
- return;
253573
- }
253574
- const projection = {};
253575
- for (const field of fields.split(",")) {
253576
- const trimmed = field.trim();
253577
- if (trimmed) {
253578
- projection[trimmed] = 1;
253579
- }
253580
- }
253581
- return Object.keys(projection).length > 0 ? projection : undefined;
253582
- }
253583
253756
  async function createEntityRoutes(db2, logger2, broadcast) {
253584
- const router = import_express3.Router({ mergeParams: true });
253585
- const parseBody = import_express3.json();
253757
+ const router = import_express4.Router({ mergeParams: true });
253758
+ const parseBody = import_express4.json();
253586
253759
  function withCollection(handler) {
253587
253760
  return async (req, res) => {
253588
253761
  const collection = db2.getCollection(req.params.entityName);
@@ -253627,42 +253800,14 @@ async function createEntityRoutes(db2, logger2, broadcast) {
253627
253800
  router.get("/:entityName", withCollection(async (req, res, collection) => {
253628
253801
  const { entityName } = req.params;
253629
253802
  try {
253630
- const { sort, limit, skip: skip2, fields, q: q13 } = req.query;
253631
- let query = {};
253632
- if (q13 && typeof q13 === "string") {
253633
- try {
253634
- query = JSON.parse(q13);
253635
- } catch {
253636
- res.status(400).json({ error: "Invalid query parameter 'q'" });
253637
- return;
253638
- }
253639
- }
253640
- let cursor3 = collection.findAsync(query);
253641
- const sortObj = parseSort(sort);
253642
- if (sortObj) {
253643
- cursor3 = cursor3.sort(sortObj);
253644
- }
253645
- if (skip2) {
253646
- const skipNum = Number.parseInt(skip2, 10);
253647
- if (!Number.isNaN(skipNum)) {
253648
- cursor3 = cursor3.skip(skipNum);
253649
- }
253650
- }
253651
- if (limit) {
253652
- const limitNum = Number.parseInt(limit, 10);
253653
- if (!Number.isNaN(limitNum)) {
253654
- cursor3 = cursor3.limit(limitNum);
253655
- }
253656
- }
253657
- const projection = parseFields(fields);
253658
- if (projection) {
253659
- cursor3 = cursor3.projection(projection);
253660
- }
253661
- const docs = await cursor3;
253662
- res.json(stripInternalFields(docs));
253803
+ res.json(stripInternalFields(await queryEntity(collection, req.query)));
253663
253804
  } catch (error48) {
253664
- logger2.error(`Error in GET /${entityName}:`, error48);
253665
- res.status(500).json({ error: "Internal server error" });
253805
+ if (error48 instanceof InvalidInputError) {
253806
+ res.status(400).json({ error: error48.message });
253807
+ } else {
253808
+ logger2.error(`Error in GET /${entityName}:`, error48);
253809
+ res.status(500).json({ error: "Internal server error" });
253810
+ }
253666
253811
  }
253667
253812
  }));
253668
253813
  router.post("/:entityName", parseBody, withCollection(async (req, res, collection) => {
@@ -253781,7 +253926,7 @@ async function createEntityRoutes(db2, logger2, broadcast) {
253781
253926
  }
253782
253927
 
253783
253928
  // src/cli/dev/dev-server/routes/integrations.ts
253784
- var import_express4 = __toESM(require_express(), 1);
253929
+ var import_express5 = __toESM(require_express(), 1);
253785
253930
  var import_multer = __toESM(require_multer(), 1);
253786
253931
  import { createHash, randomUUID as randomUUID4 } from "node:crypto";
253787
253932
  import fs28 from "node:fs";
@@ -253790,8 +253935,8 @@ function createFileToken(fileUri) {
253790
253935
  return createHash("sha256").update(fileUri).digest("hex");
253791
253936
  }
253792
253937
  function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger2) {
253793
- const router = import_express4.Router({ mergeParams: true });
253794
- const parseBody = import_express4.json();
253938
+ const router = import_express5.Router({ mergeParams: true });
253939
+ const parseBody = import_express5.json();
253795
253940
  const privateFilesDir = path18.join(mediaFilesDir, "private");
253796
253941
  fs28.mkdirSync(mediaFilesDir, { recursive: true });
253797
253942
  fs28.mkdirSync(privateFilesDir, { recursive: true });
@@ -253861,7 +254006,7 @@ function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger2) {
253861
254006
  return router;
253862
254007
  }
253863
254008
  function createCustomIntegrationRoutes(remoteProxy, logger2) {
253864
- const router = import_express4.Router({ mergeParams: true });
254009
+ const router = import_express5.Router({ mergeParams: true });
253865
254010
  router.post("/:slug/:operationId", (req, res, next) => {
253866
254011
  logger2.warn(`"${req.originalUrl}" is not supported in local development, passing call to production`);
253867
254012
  req.url = req.originalUrl;
@@ -255570,11 +255715,11 @@ class WatchBase44 extends EventEmitter4 {
255570
255715
  var DEFAULT_PORT = 4400;
255571
255716
  var BASE44_APP_URL = "https://base44.app";
255572
255717
  async function createDevServer(options8) {
255573
- const { port: userPort } = options8;
255718
+ const { port: userPort, cwd } = options8;
255574
255719
  const port = userPort ?? await getPorts({ port: DEFAULT_PORT });
255575
255720
  const baseUrl = `http://localhost:${port}`;
255576
255721
  const { functions, entities, project: project2 } = await options8.loadResources();
255577
- const app = import_express5.default();
255722
+ const app = import_express6.default();
255578
255723
  const remoteProxy = import_http_proxy_middleware2.createProxyMiddleware({
255579
255724
  target: BASE44_APP_URL,
255580
255725
  changeOrigin: true
@@ -255606,6 +255751,8 @@ async function createDevServer(options8) {
255606
255751
  let emitEntityEvent = () => {};
255607
255752
  const entityRoutes = await createEntityRoutes(db2, devLogger, (...args) => emitEntityEvent(...args));
255608
255753
  app.use("/api/apps/:appId/entities", entityRoutes);
255754
+ const authRouter = createAuthRouter(db2, devLogger);
255755
+ app.use("/api/apps/:appId/auth", authRouter);
255609
255756
  const { path: mediaFilesDir } = await $dir();
255610
255757
  app.use("/media/private/:fileUri", (req, res, next) => {
255611
255758
  const { fileUri } = req.params;
@@ -255625,13 +255772,15 @@ async function createDevServer(options8) {
255625
255772
  }
255626
255773
  next();
255627
255774
  });
255628
- app.use("/media", import_express5.default.static(mediaFilesDir));
255775
+ app.use("/media", import_express6.default.static(mediaFilesDir));
255629
255776
  const integrationRoutes = createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, devLogger);
255630
255777
  app.use("/api/apps/:appId/integration-endpoints", integrationRoutes);
255631
255778
  const customIntegrationRoutes = createCustomIntegrationRoutes(remoteProxy, devLogger);
255632
255779
  app.use("/api/apps/:appId/integrations/custom", customIntegrationRoutes);
255633
255780
  app.use((req, res, next) => {
255634
- devLogger.warn(`"${req.originalUrl}" is not supported in local development, passing call to production`);
255781
+ if (!req.originalUrl.endsWith("analytics/track/batch")) {
255782
+ devLogger.warn(`"${req.originalUrl}" is not supported in local development, passing call to production`);
255783
+ }
255635
255784
  remoteProxy(req, res, next);
255636
255785
  });
255637
255786
  const server = await new Promise((resolve8, reject) => {
@@ -255702,6 +255851,7 @@ async function devAction({ log }, options8) {
255702
255851
  const { port: resolvedPort } = await createDevServer({
255703
255852
  log,
255704
255853
  port,
255854
+ cwd: process21.cwd(),
255705
255855
  denoWrapperPath: getDenoWrapperPath(),
255706
255856
  loadResources: async () => {
255707
255857
  const { functions, entities, project: project2 } = await readProjectConfig();
@@ -260209,4 +260359,4 @@ export {
260209
260359
  CLIExitError
260210
260360
  };
260211
260361
 
260212
- //# debugId=7DD396B284C982D564756E2164756E21
260362
+ //# debugId=5FDDF606296BF31964756E2164756E21