@base44-preview/cli 0.0.50-pr.477.43f5b00 → 0.0.50-pr.481.773d5d4
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 +507 -97
- package/dist/cli/index.js.map +15 -12
- package/package.json +1 -1
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) {
|
|
@@ -235041,8 +235042,8 @@ var TOKEN_REFRESH_BUFFER_MS = 60 * 1000;
|
|
|
235041
235042
|
var refreshPromise = null;
|
|
235042
235043
|
async function readAuth() {
|
|
235043
235044
|
try {
|
|
235044
|
-
const
|
|
235045
|
-
const result = AuthDataSchema.safeParse(
|
|
235045
|
+
const authData = await readJsonFile(getAuthFilePath());
|
|
235046
|
+
const result = AuthDataSchema.safeParse(authData);
|
|
235046
235047
|
if (!result.success) {
|
|
235047
235048
|
throw new SchemaValidationError("Invalid authentication data", result.error, getAuthFilePath());
|
|
235048
235049
|
}
|
|
@@ -243210,10 +243211,12 @@ var package_default = {
|
|
|
243210
243211
|
"@types/ejs": "^3.1.5",
|
|
243211
243212
|
"@types/express": "^5.0.6",
|
|
243212
243213
|
"@types/json-schema": "^7.0.15",
|
|
243214
|
+
"@types/jsonwebtoken": "^9.0.10",
|
|
243213
243215
|
"@types/lodash": "^4.17.24",
|
|
243214
243216
|
"@types/multer": "^2.0.0",
|
|
243215
243217
|
"@types/node": "^22.10.5",
|
|
243216
243218
|
"@vercel/detect-agent": "^1.1.0",
|
|
243219
|
+
outdent: "^0.8.0",
|
|
243217
243220
|
chalk: "^5.6.2",
|
|
243218
243221
|
chokidar: "^5.0.0",
|
|
243219
243222
|
commander: "^12.1.0",
|
|
@@ -243228,6 +243231,7 @@ var package_default = {
|
|
|
243228
243231
|
globby: "^16.1.0",
|
|
243229
243232
|
"http-proxy-middleware": "^3.0.5",
|
|
243230
243233
|
"json-schema-to-typescript": "^15.0.4",
|
|
243234
|
+
jsonwebtoken: "^9.0.3",
|
|
243231
243235
|
json5: "^2.2.3",
|
|
243232
243236
|
ky: "^1.14.2",
|
|
243233
243237
|
lodash: "^4.17.23",
|
|
@@ -243243,6 +243247,7 @@ var package_default = {
|
|
|
243243
243247
|
typescript: "^5.7.2",
|
|
243244
243248
|
vitest: "^4.0.16",
|
|
243245
243249
|
yaml: "^2.8.2",
|
|
243250
|
+
qs: "^6.12.3",
|
|
243246
243251
|
zod: "^4.3.5"
|
|
243247
243252
|
},
|
|
243248
243253
|
engines: {
|
|
@@ -252755,9 +252760,12 @@ function getTypesCommand() {
|
|
|
252755
252760
|
return new Command("types").description("Manage TypeScript type generation").addCommand(getTypesGenerateCommand());
|
|
252756
252761
|
}
|
|
252757
252762
|
|
|
252763
|
+
// src/cli/commands/dev.ts
|
|
252764
|
+
import process21 from "node:process";
|
|
252765
|
+
|
|
252758
252766
|
// src/cli/dev/dev-server/main.ts
|
|
252759
252767
|
var import_cors = __toESM(require_lib4(), 1);
|
|
252760
|
-
var
|
|
252768
|
+
var import_express6 = __toESM(require_express(), 1);
|
|
252761
252769
|
import { dirname as dirname16, join as join23 } from "node:path";
|
|
252762
252770
|
|
|
252763
252771
|
// ../../node_modules/get-port/index.js
|
|
@@ -252931,6 +252939,7 @@ function createDevLogger() {
|
|
|
252931
252939
|
|
|
252932
252940
|
// src/cli/dev/dev-server/function-manager.ts
|
|
252933
252941
|
import { spawn as spawn2 } from "node:child_process";
|
|
252942
|
+
import { pathToFileURL } from "node:url";
|
|
252934
252943
|
var READY_TIMEOUT = 30000;
|
|
252935
252944
|
|
|
252936
252945
|
class FunctionManager {
|
|
@@ -253010,7 +253019,7 @@ class FunctionManager {
|
|
|
253010
253019
|
const process21 = spawn2("deno", ["run", "--allow-all", this.wrapperPath], {
|
|
253011
253020
|
env: {
|
|
253012
253021
|
...globalThis.process.env,
|
|
253013
|
-
FUNCTION_PATH: func.entryPath,
|
|
253022
|
+
FUNCTION_PATH: pathToFileURL(func.entryPath).href,
|
|
253014
253023
|
FUNCTION_PORT: String(port),
|
|
253015
253024
|
FUNCTION_NAME: func.name
|
|
253016
253025
|
},
|
|
@@ -253089,9 +253098,13 @@ function createFunctionRouter(manager, logger2) {
|
|
|
253089
253098
|
on: {
|
|
253090
253099
|
proxyReq: (proxyReq, req) => {
|
|
253091
253100
|
const xAppId = req.headers["x-app-id"];
|
|
253101
|
+
const authorization = req.headers.authorization;
|
|
253092
253102
|
if (xAppId) {
|
|
253093
253103
|
proxyReq.setHeader("Base44-App-Id", xAppId);
|
|
253094
253104
|
}
|
|
253105
|
+
if (authorization) {
|
|
253106
|
+
proxyReq.setHeader("Base44-Service-Authorization", authorization);
|
|
253107
|
+
}
|
|
253095
253108
|
proxyReq.setHeader("Base44-Api-Url", `${req.protocol}://${req.headers.host}`);
|
|
253096
253109
|
},
|
|
253097
253110
|
error: (err, _req, res) => {
|
|
@@ -253316,7 +253329,9 @@ class Validator {
|
|
|
253316
253329
|
}
|
|
253317
253330
|
|
|
253318
253331
|
// src/cli/dev/dev-server/db/database.ts
|
|
253332
|
+
var PRIVATE_COLLECTION_PREFIX = "$";
|
|
253319
253333
|
var USER_COLLECTION = "user";
|
|
253334
|
+
var PRIVATE_USER_COLLECTION = PRIVATE_COLLECTION_PREFIX + USER_COLLECTION;
|
|
253320
253335
|
|
|
253321
253336
|
class Database {
|
|
253322
253337
|
collections = new Map;
|
|
@@ -253338,6 +253353,7 @@ class Database {
|
|
|
253338
253353
|
this.schemas.set(USER_COLLECTION, this.buildUserSchema(userEntity));
|
|
253339
253354
|
const collection = new import_nedb.default;
|
|
253340
253355
|
this.collections.set(USER_COLLECTION, collection);
|
|
253356
|
+
this.collections.set(PRIVATE_USER_COLLECTION, new import_nedb.default);
|
|
253341
253357
|
const userInfo = await readAuth();
|
|
253342
253358
|
const now = getNowISOTimestamp();
|
|
253343
253359
|
await collection.insertAsync({
|
|
@@ -253378,8 +253394,13 @@ class Database {
|
|
|
253378
253394
|
getCollection(name2) {
|
|
253379
253395
|
return this.collections.get(this.normalizeName(name2));
|
|
253380
253396
|
}
|
|
253397
|
+
getSchema(entityName) {
|
|
253398
|
+
return this.schemas.get(this.normalizeName(entityName));
|
|
253399
|
+
}
|
|
253381
253400
|
getCollectionNames() {
|
|
253382
|
-
return Array.from(this.collections.keys())
|
|
253401
|
+
return Array.from(this.collections.keys()).filter((name2) => {
|
|
253402
|
+
return !name2.startsWith(PRIVATE_COLLECTION_PREFIX);
|
|
253403
|
+
});
|
|
253383
253404
|
}
|
|
253384
253405
|
dropAll() {
|
|
253385
253406
|
for (const collection of this.collections.values()) {
|
|
@@ -253443,15 +253464,339 @@ function broadcastEntityEvent(io6, appId, entityName, event) {
|
|
|
253443
253464
|
});
|
|
253444
253465
|
}
|
|
253445
253466
|
|
|
253446
|
-
// src/cli/dev/dev-server/routes/
|
|
253447
|
-
var import_express3 = __toESM(require_express(), 1);
|
|
253448
|
-
|
|
253449
|
-
// src/cli/dev/dev-server/routes/entities/entities-user-router.ts
|
|
253467
|
+
// src/cli/dev/dev-server/routes/auth-router.ts
|
|
253450
253468
|
var import_express2 = __toESM(require_express(), 1);
|
|
253451
253469
|
var import_jsonwebtoken = __toESM(require_jsonwebtoken(), 1);
|
|
253452
|
-
|
|
253470
|
+
import { randomInt } from "node:crypto";
|
|
253471
|
+
var LOCAL_DEV_SECRET = "LOCAL_DEV_SECRET";
|
|
253472
|
+
var generateCode = () => {
|
|
253473
|
+
return randomInt(1e5, 1e6).toString();
|
|
253474
|
+
};
|
|
253475
|
+
var createJwtToken = (email3) => {
|
|
253476
|
+
return import_jsonwebtoken.default.sign({ sub: email3 }, LOCAL_DEV_SECRET, {
|
|
253477
|
+
expiresIn: "360d"
|
|
253478
|
+
});
|
|
253479
|
+
};
|
|
253480
|
+
var LoginBody = object({ email: email2(), password: string2() });
|
|
253481
|
+
var VerifyOtpBody = object({ email: email2(), otp_code: string2() });
|
|
253482
|
+
function createAuthRouter(db2, logger2) {
|
|
253453
253483
|
const router = import_express2.Router({ mergeParams: true });
|
|
253454
253484
|
const parseBody = import_express2.json();
|
|
253485
|
+
router.post("/login", parseBody, async (req, res) => {
|
|
253486
|
+
const { email: email3, password } = LoginBody.parse(req.body);
|
|
253487
|
+
const result = await db2.getCollection(USER_COLLECTION)?.findOneAsync({ email: email3 });
|
|
253488
|
+
if (result) {
|
|
253489
|
+
const privateUserData = await db2.getCollection(PRIVATE_USER_COLLECTION)?.findOneAsync({ email: email3 });
|
|
253490
|
+
if (result.role === "admin" || privateUserData?.password === password) {
|
|
253491
|
+
res.json({
|
|
253492
|
+
access_token: createJwtToken(email3),
|
|
253493
|
+
success: true,
|
|
253494
|
+
user: {}
|
|
253495
|
+
});
|
|
253496
|
+
} else {
|
|
253497
|
+
res.status(400).json({
|
|
253498
|
+
detail: "Invalid email or password",
|
|
253499
|
+
error_type: "HTTPException",
|
|
253500
|
+
message: "Invalid email or password",
|
|
253501
|
+
request_id: null,
|
|
253502
|
+
traceback: ""
|
|
253503
|
+
});
|
|
253504
|
+
}
|
|
253505
|
+
return;
|
|
253506
|
+
}
|
|
253507
|
+
res.status(401).json({ error: "Unauthorized" });
|
|
253508
|
+
});
|
|
253509
|
+
router.post("/register", parseBody, async (req, res) => {
|
|
253510
|
+
const { email: email3, password } = LoginBody.parse(req.body);
|
|
253511
|
+
if ((password || "").length < 8) {
|
|
253512
|
+
res.status(400).json({
|
|
253513
|
+
detail: "Password must be at least 8 characters long",
|
|
253514
|
+
error_type: "HTTPException",
|
|
253515
|
+
message: "Password must be at least 8 characters long",
|
|
253516
|
+
request_id: null,
|
|
253517
|
+
traceback: ""
|
|
253518
|
+
});
|
|
253519
|
+
return;
|
|
253520
|
+
}
|
|
253521
|
+
const result = await db2.getCollection(USER_COLLECTION)?.findOneAsync({ email: email3 });
|
|
253522
|
+
if (result) {
|
|
253523
|
+
res.status(400).json({
|
|
253524
|
+
detail: "A user with this email already exists",
|
|
253525
|
+
error_type: "HTTPException",
|
|
253526
|
+
message: "A user with this email already exists",
|
|
253527
|
+
request_id: null,
|
|
253528
|
+
traceback: ""
|
|
253529
|
+
});
|
|
253530
|
+
return;
|
|
253531
|
+
}
|
|
253532
|
+
const privateUserCollection = db2.getCollection(PRIVATE_USER_COLLECTION);
|
|
253533
|
+
const privateUserData = await privateUserCollection?.findOneAsync({
|
|
253534
|
+
email: email3
|
|
253535
|
+
});
|
|
253536
|
+
const otpCode = generateCode();
|
|
253537
|
+
const id2 = privateUserData ? privateUserData.id : nanoid3();
|
|
253538
|
+
if (!privateUserData) {
|
|
253539
|
+
await privateUserCollection?.insertAsync({
|
|
253540
|
+
id: id2,
|
|
253541
|
+
email: email3,
|
|
253542
|
+
otpCode,
|
|
253543
|
+
password,
|
|
253544
|
+
createdAt: Date.now()
|
|
253545
|
+
});
|
|
253546
|
+
} else {
|
|
253547
|
+
await privateUserCollection?.updateAsync({
|
|
253548
|
+
email: email3
|
|
253549
|
+
}, {
|
|
253550
|
+
$set: {
|
|
253551
|
+
otpCode,
|
|
253552
|
+
createdAt: Date.now()
|
|
253553
|
+
}
|
|
253554
|
+
});
|
|
253555
|
+
}
|
|
253556
|
+
logger2.log(theme.styles.info(`
|
|
253557
|
+
In order to complete registration use this verification code: ${otpCode}
|
|
253558
|
+
`));
|
|
253559
|
+
res.json({
|
|
253560
|
+
id: id2,
|
|
253561
|
+
message: "Registration successful. Please check your email for the verification code.",
|
|
253562
|
+
otp_expires_in_minutes: 10
|
|
253563
|
+
});
|
|
253564
|
+
});
|
|
253565
|
+
router.post("/verify-otp", parseBody, async (req, res) => {
|
|
253566
|
+
const { email: email3, otp_code } = VerifyOtpBody.parse(req.body);
|
|
253567
|
+
const privateUserCollection = db2.getCollection(PRIVATE_USER_COLLECTION);
|
|
253568
|
+
const privateUserData = await privateUserCollection?.findOneAsync({
|
|
253569
|
+
email: email3
|
|
253570
|
+
});
|
|
253571
|
+
if (privateUserData && privateUserData.otpCode === otp_code) {
|
|
253572
|
+
if (+Date.now() - privateUserData.createdAt < 10 * 60 * 1000) {
|
|
253573
|
+
await privateUserCollection?.updateAsync({
|
|
253574
|
+
email: email3
|
|
253575
|
+
}, {
|
|
253576
|
+
$unset: { otpCode: true }
|
|
253577
|
+
});
|
|
253578
|
+
const collection = db2.getCollection(USER_COLLECTION);
|
|
253579
|
+
const now = getNowISOTimestamp();
|
|
253580
|
+
const nameFromEmailMatch = /^([^@]+)/.exec(email3);
|
|
253581
|
+
const fullName = nameFromEmailMatch ? nameFromEmailMatch[1] : email3;
|
|
253582
|
+
await collection?.insertAsync({
|
|
253583
|
+
id: privateUserData.id,
|
|
253584
|
+
email: email3,
|
|
253585
|
+
full_name: fullName,
|
|
253586
|
+
is_service: false,
|
|
253587
|
+
is_verified: true,
|
|
253588
|
+
disabled: null,
|
|
253589
|
+
role: "user",
|
|
253590
|
+
collaborator_role: "editor",
|
|
253591
|
+
created_date: now,
|
|
253592
|
+
updated_date: now
|
|
253593
|
+
});
|
|
253594
|
+
res.json({
|
|
253595
|
+
id: privateUserData.id,
|
|
253596
|
+
access_token: createJwtToken(email3),
|
|
253597
|
+
message: "Email verified successfully. You are now logged in.",
|
|
253598
|
+
success: true
|
|
253599
|
+
});
|
|
253600
|
+
} else {
|
|
253601
|
+
res.status(400).json({
|
|
253602
|
+
detail: "Verification code has expired",
|
|
253603
|
+
error_type: "HTTPException",
|
|
253604
|
+
message: "Verification code has expired",
|
|
253605
|
+
request_id: null,
|
|
253606
|
+
traceback: ""
|
|
253607
|
+
});
|
|
253608
|
+
}
|
|
253609
|
+
} else {
|
|
253610
|
+
const appId = req.params.appId;
|
|
253611
|
+
res.status(500).json({
|
|
253612
|
+
detail: `{'email': '${email3}', 'app_id': '${appId}}'} -> Object not found`,
|
|
253613
|
+
error_type: "ObjectNotFoundError",
|
|
253614
|
+
message: `{'email': '${email3}', 'app_id': '${appId}}'} -> Object not found`,
|
|
253615
|
+
request_id: null,
|
|
253616
|
+
traceback: ""
|
|
253617
|
+
});
|
|
253618
|
+
}
|
|
253619
|
+
});
|
|
253620
|
+
return router;
|
|
253621
|
+
}
|
|
253622
|
+
|
|
253623
|
+
// src/cli/dev/dev-server/routes/entities/entities-router.ts
|
|
253624
|
+
var import_express4 = __toESM(require_express(), 1);
|
|
253625
|
+
var import_jsonwebtoken3 = __toESM(require_jsonwebtoken(), 1);
|
|
253626
|
+
|
|
253627
|
+
// src/cli/dev/dev-server/db/rls.ts
|
|
253628
|
+
function resolveTemplate(value, user) {
|
|
253629
|
+
return value.replace(/\{\{user\.([\w.]+)\}\}/g, (_match, path18) => {
|
|
253630
|
+
if (path18.startsWith("data.")) {
|
|
253631
|
+
return String(user[path18.slice(5)] ?? "");
|
|
253632
|
+
}
|
|
253633
|
+
return String(user[path18] ?? "");
|
|
253634
|
+
});
|
|
253635
|
+
}
|
|
253636
|
+
function getRecordField(key2, record2) {
|
|
253637
|
+
if (key2.startsWith("data.")) {
|
|
253638
|
+
return record2[key2.slice(5)];
|
|
253639
|
+
}
|
|
253640
|
+
return record2[key2];
|
|
253641
|
+
}
|
|
253642
|
+
function evaluateOperator(recordValue, operator) {
|
|
253643
|
+
for (const [op2, opValue] of Object.entries(operator)) {
|
|
253644
|
+
switch (op2) {
|
|
253645
|
+
case "$in":
|
|
253646
|
+
if (!Array.isArray(opValue) || !opValue.includes(recordValue))
|
|
253647
|
+
return false;
|
|
253648
|
+
break;
|
|
253649
|
+
case "$nin":
|
|
253650
|
+
if (Array.isArray(opValue) && opValue.includes(recordValue))
|
|
253651
|
+
return false;
|
|
253652
|
+
break;
|
|
253653
|
+
case "$ne":
|
|
253654
|
+
if (recordValue === opValue)
|
|
253655
|
+
return false;
|
|
253656
|
+
break;
|
|
253657
|
+
case "$all":
|
|
253658
|
+
if (!Array.isArray(recordValue) || !Array.isArray(opValue))
|
|
253659
|
+
return false;
|
|
253660
|
+
if (!opValue.every((v10) => recordValue.includes(v10)))
|
|
253661
|
+
return false;
|
|
253662
|
+
break;
|
|
253663
|
+
}
|
|
253664
|
+
}
|
|
253665
|
+
return true;
|
|
253666
|
+
}
|
|
253667
|
+
function evaluateUserCondition(condition, user) {
|
|
253668
|
+
for (const [key2, expected] of Object.entries(condition)) {
|
|
253669
|
+
const userValue = key2.startsWith("data.") ? user[key2.slice(5)] : user[key2];
|
|
253670
|
+
if (typeof expected === "object" && expected !== null) {
|
|
253671
|
+
if (!evaluateOperator(userValue, expected))
|
|
253672
|
+
return false;
|
|
253673
|
+
} else {
|
|
253674
|
+
if (userValue !== expected)
|
|
253675
|
+
return false;
|
|
253676
|
+
}
|
|
253677
|
+
}
|
|
253678
|
+
return true;
|
|
253679
|
+
}
|
|
253680
|
+
function evaluateCondition(condition, record2, user) {
|
|
253681
|
+
for (const [key2, value] of Object.entries(condition)) {
|
|
253682
|
+
if (key2 === "user_condition") {
|
|
253683
|
+
if (!evaluateUserCondition(value, user))
|
|
253684
|
+
return false;
|
|
253685
|
+
continue;
|
|
253686
|
+
}
|
|
253687
|
+
if (key2 === "$or") {
|
|
253688
|
+
const conditions = value;
|
|
253689
|
+
if (!conditions.some((c8) => evaluateCondition(c8, record2, user)))
|
|
253690
|
+
return false;
|
|
253691
|
+
continue;
|
|
253692
|
+
}
|
|
253693
|
+
if (key2 === "$and") {
|
|
253694
|
+
const conditions = value;
|
|
253695
|
+
if (!conditions.every((c8) => evaluateCondition(c8, record2, user)))
|
|
253696
|
+
return false;
|
|
253697
|
+
continue;
|
|
253698
|
+
}
|
|
253699
|
+
if (key2 === "$nor") {
|
|
253700
|
+
const conditions = value;
|
|
253701
|
+
if (conditions.some((c8) => evaluateCondition(c8, record2, user)))
|
|
253702
|
+
return false;
|
|
253703
|
+
continue;
|
|
253704
|
+
}
|
|
253705
|
+
const recordValue = getRecordField(key2, record2);
|
|
253706
|
+
const resolvedValue = typeof value === "string" ? resolveTemplate(value, user) : value;
|
|
253707
|
+
if (typeof resolvedValue === "object" && resolvedValue !== null) {
|
|
253708
|
+
if (!evaluateOperator(recordValue, resolvedValue))
|
|
253709
|
+
return false;
|
|
253710
|
+
} else {
|
|
253711
|
+
if (recordValue !== resolvedValue)
|
|
253712
|
+
return false;
|
|
253713
|
+
}
|
|
253714
|
+
}
|
|
253715
|
+
return true;
|
|
253716
|
+
}
|
|
253717
|
+
function checkRLS(rule, record2, user) {
|
|
253718
|
+
if (rule === undefined)
|
|
253719
|
+
return true;
|
|
253720
|
+
if (typeof rule === "boolean")
|
|
253721
|
+
return rule;
|
|
253722
|
+
if (!user)
|
|
253723
|
+
return false;
|
|
253724
|
+
return evaluateCondition(rule, record2, user);
|
|
253725
|
+
}
|
|
253726
|
+
function applyFLS(record2, schema10, user, operation) {
|
|
253727
|
+
const result = {};
|
|
253728
|
+
for (const [key2, value] of Object.entries(record2)) {
|
|
253729
|
+
const rule = schema10.properties[key2]?.rls?.[operation];
|
|
253730
|
+
if (!rule || checkRLS(rule, record2, user)) {
|
|
253731
|
+
result[key2] = value;
|
|
253732
|
+
}
|
|
253733
|
+
}
|
|
253734
|
+
return result;
|
|
253735
|
+
}
|
|
253736
|
+
|
|
253737
|
+
// src/cli/dev/dev-server/db/entity-queries.ts
|
|
253738
|
+
function parseSort(sort) {
|
|
253739
|
+
if (!sort) {
|
|
253740
|
+
return;
|
|
253741
|
+
}
|
|
253742
|
+
if (sort.startsWith("-")) {
|
|
253743
|
+
return { [sort.slice(1)]: -1 };
|
|
253744
|
+
}
|
|
253745
|
+
return { [sort]: 1 };
|
|
253746
|
+
}
|
|
253747
|
+
function parseFields(fields) {
|
|
253748
|
+
if (!fields) {
|
|
253749
|
+
return;
|
|
253750
|
+
}
|
|
253751
|
+
const projection = {};
|
|
253752
|
+
for (const field of fields.split(",")) {
|
|
253753
|
+
const trimmed = field.trim();
|
|
253754
|
+
if (trimmed) {
|
|
253755
|
+
projection[trimmed] = 1;
|
|
253756
|
+
}
|
|
253757
|
+
}
|
|
253758
|
+
return Object.keys(projection).length > 0 ? projection : undefined;
|
|
253759
|
+
}
|
|
253760
|
+
var queryEntity = async (collection, reqQuery) => {
|
|
253761
|
+
const { sort, limit, skip: skip2, fields, q: q13 } = reqQuery;
|
|
253762
|
+
let query = {};
|
|
253763
|
+
if (q13 && typeof q13 === "string") {
|
|
253764
|
+
try {
|
|
253765
|
+
query = JSON.parse(q13);
|
|
253766
|
+
} catch {
|
|
253767
|
+
throw new InvalidInputError("Invalid query parameter 'q'");
|
|
253768
|
+
}
|
|
253769
|
+
}
|
|
253770
|
+
let cursor3 = collection.findAsync(query);
|
|
253771
|
+
const sortObj = parseSort(sort);
|
|
253772
|
+
if (sortObj) {
|
|
253773
|
+
cursor3 = cursor3.sort(sortObj);
|
|
253774
|
+
}
|
|
253775
|
+
if (skip2) {
|
|
253776
|
+
const skipNum = Number.parseInt(skip2, 10);
|
|
253777
|
+
if (!Number.isNaN(skipNum)) {
|
|
253778
|
+
cursor3 = cursor3.skip(skipNum);
|
|
253779
|
+
}
|
|
253780
|
+
}
|
|
253781
|
+
if (limit) {
|
|
253782
|
+
const limitNum = Number.parseInt(limit, 10);
|
|
253783
|
+
if (!Number.isNaN(limitNum)) {
|
|
253784
|
+
cursor3 = cursor3.limit(limitNum);
|
|
253785
|
+
}
|
|
253786
|
+
}
|
|
253787
|
+
const projection = parseFields(fields);
|
|
253788
|
+
if (projection) {
|
|
253789
|
+
cursor3 = cursor3.projection(projection);
|
|
253790
|
+
}
|
|
253791
|
+
return cursor3;
|
|
253792
|
+
};
|
|
253793
|
+
|
|
253794
|
+
// src/cli/dev/dev-server/routes/entities/entities-user-router.ts
|
|
253795
|
+
var import_express3 = __toESM(require_express(), 1);
|
|
253796
|
+
var import_jsonwebtoken2 = __toESM(require_jsonwebtoken(), 1);
|
|
253797
|
+
function createUserRouter(db2, logger2) {
|
|
253798
|
+
const router = import_express3.Router({ mergeParams: true });
|
|
253799
|
+
const parseBody = import_express3.json();
|
|
253455
253800
|
function withAuth(handler) {
|
|
253456
253801
|
return async (req, res) => {
|
|
253457
253802
|
const auth2 = req.headers.authorization;
|
|
@@ -253460,13 +253805,13 @@ function createUserRouter(db2, logger2) {
|
|
|
253460
253805
|
return;
|
|
253461
253806
|
}
|
|
253462
253807
|
try {
|
|
253463
|
-
const { payload } =
|
|
253464
|
-
const
|
|
253465
|
-
if (!
|
|
253808
|
+
const { payload } = import_jsonwebtoken2.default.decode(auth2.replace("Bearer ", ""), { complete: true }) ?? {};
|
|
253809
|
+
const currentUser = await db2.getCollection(USER_COLLECTION)?.findOneAsync({ email: payload?.sub });
|
|
253810
|
+
if (!currentUser) {
|
|
253466
253811
|
res.status(404).json({ error: "Unable to read data for the current user" });
|
|
253467
253812
|
return;
|
|
253468
253813
|
}
|
|
253469
|
-
await handler(req, res,
|
|
253814
|
+
await handler(req, res, currentUser);
|
|
253470
253815
|
} catch {
|
|
253471
253816
|
res.status(401).json({ error: "Unauthorized" });
|
|
253472
253817
|
}
|
|
@@ -253493,6 +253838,28 @@ function createUserRouter(db2, logger2) {
|
|
|
253493
253838
|
...req.body
|
|
253494
253839
|
});
|
|
253495
253840
|
}));
|
|
253841
|
+
router.get("/", withAuth(async (req, res, currentUser) => {
|
|
253842
|
+
const collection = db2.getCollection(USER_COLLECTION);
|
|
253843
|
+
if (!collection) {
|
|
253844
|
+
res.status(404).json({ error: `Entity "${USER_COLLECTION}" not found` });
|
|
253845
|
+
return;
|
|
253846
|
+
}
|
|
253847
|
+
try {
|
|
253848
|
+
if (currentUser.role === "admin") {
|
|
253849
|
+
const result = await queryEntity(collection, req.query);
|
|
253850
|
+
res.json(stripInternalFields(result));
|
|
253851
|
+
} else {
|
|
253852
|
+
res.json([stripInternalFields(currentUser)]);
|
|
253853
|
+
}
|
|
253854
|
+
} catch (error48) {
|
|
253855
|
+
if (error48 instanceof InvalidInputError) {
|
|
253856
|
+
res.status(400).json({ error: error48.message });
|
|
253857
|
+
} else {
|
|
253858
|
+
logger2.error(`Error in GET /${USER_COLLECTION}:`, error48);
|
|
253859
|
+
res.status(500).json({ error: "Internal server error" });
|
|
253860
|
+
}
|
|
253861
|
+
}
|
|
253862
|
+
}));
|
|
253496
253863
|
router.post("/bulk", async (_req, res) => {
|
|
253497
253864
|
res.json({});
|
|
253498
253865
|
});
|
|
@@ -253542,31 +253909,9 @@ function createUserRouter(db2, logger2) {
|
|
|
253542
253909
|
}
|
|
253543
253910
|
|
|
253544
253911
|
// src/cli/dev/dev-server/routes/entities/entities-router.ts
|
|
253545
|
-
function parseSort(sort) {
|
|
253546
|
-
if (!sort) {
|
|
253547
|
-
return;
|
|
253548
|
-
}
|
|
253549
|
-
if (sort.startsWith("-")) {
|
|
253550
|
-
return { [sort.slice(1)]: -1 };
|
|
253551
|
-
}
|
|
253552
|
-
return { [sort]: 1 };
|
|
253553
|
-
}
|
|
253554
|
-
function parseFields(fields) {
|
|
253555
|
-
if (!fields) {
|
|
253556
|
-
return;
|
|
253557
|
-
}
|
|
253558
|
-
const projection = {};
|
|
253559
|
-
for (const field of fields.split(",")) {
|
|
253560
|
-
const trimmed = field.trim();
|
|
253561
|
-
if (trimmed) {
|
|
253562
|
-
projection[trimmed] = 1;
|
|
253563
|
-
}
|
|
253564
|
-
}
|
|
253565
|
-
return Object.keys(projection).length > 0 ? projection : undefined;
|
|
253566
|
-
}
|
|
253567
253912
|
async function createEntityRoutes(db2, logger2, broadcast) {
|
|
253568
|
-
const router =
|
|
253569
|
-
const parseBody =
|
|
253913
|
+
const router = import_express4.Router({ mergeParams: true });
|
|
253914
|
+
const parseBody = import_express4.json();
|
|
253570
253915
|
function withCollection(handler) {
|
|
253571
253916
|
return async (req, res) => {
|
|
253572
253917
|
const collection = db2.getCollection(req.params.entityName);
|
|
@@ -253574,7 +253919,13 @@ async function createEntityRoutes(db2, logger2, broadcast) {
|
|
|
253574
253919
|
res.status(404).json({ error: `Entity "${req.params.entityName}" not found` });
|
|
253575
253920
|
return;
|
|
253576
253921
|
}
|
|
253577
|
-
|
|
253922
|
+
let currentUser;
|
|
253923
|
+
try {
|
|
253924
|
+
const auth2 = req.headers.authorization || "";
|
|
253925
|
+
const { payload } = import_jsonwebtoken3.default.decode(auth2.replace("Bearer ", ""), { complete: true }) ?? {};
|
|
253926
|
+
currentUser = await db2.getCollection(USER_COLLECTION)?.findOneAsync({ email: payload?.sub });
|
|
253927
|
+
} catch {}
|
|
253928
|
+
await handler(req, res, collection, currentUser);
|
|
253578
253929
|
};
|
|
253579
253930
|
}
|
|
253580
253931
|
function emit(appId, entityName, type, data) {
|
|
@@ -253594,7 +253945,7 @@ async function createEntityRoutes(db2, logger2, broadcast) {
|
|
|
253594
253945
|
}
|
|
253595
253946
|
const userRouter = createUserRouter(db2, logger2);
|
|
253596
253947
|
router.use("/User", userRouter);
|
|
253597
|
-
router.get("/:entityName/:id", withCollection(async (req, res, collection) => {
|
|
253948
|
+
router.get("/:entityName/:id", withCollection(async (req, res, collection, currentUser) => {
|
|
253598
253949
|
const { entityName, id: id2 } = req.params;
|
|
253599
253950
|
try {
|
|
253600
253951
|
const doc2 = await collection.findOneAsync({ id: id2 });
|
|
@@ -253602,63 +253953,70 @@ async function createEntityRoutes(db2, logger2, broadcast) {
|
|
|
253602
253953
|
res.status(404).json({ error: `Record with id "${id2}" not found` });
|
|
253603
253954
|
return;
|
|
253604
253955
|
}
|
|
253605
|
-
|
|
253956
|
+
const schema10 = db2.getSchema(entityName);
|
|
253957
|
+
if (!checkRLS(schema10?.rls?.read, doc2, currentUser)) {
|
|
253958
|
+
res.status(403).json({ error: "Permission denied" });
|
|
253959
|
+
return;
|
|
253960
|
+
}
|
|
253961
|
+
let result = stripInternalFields(doc2);
|
|
253962
|
+
if (schema10) {
|
|
253963
|
+
result = applyFLS(result, schema10, currentUser, "read");
|
|
253964
|
+
}
|
|
253965
|
+
res.json(result);
|
|
253606
253966
|
} catch (error48) {
|
|
253607
253967
|
logger2.error(`Error in GET /${entityName}/${id2}:`, error48);
|
|
253608
253968
|
res.status(500).json({ error: "Internal server error" });
|
|
253609
253969
|
}
|
|
253610
253970
|
}));
|
|
253611
|
-
router.get("/:entityName", withCollection(async (req, res, collection) => {
|
|
253971
|
+
router.get("/:entityName", withCollection(async (req, res, collection, currentUser) => {
|
|
253612
253972
|
const { entityName } = req.params;
|
|
253613
253973
|
try {
|
|
253614
|
-
const
|
|
253615
|
-
|
|
253616
|
-
|
|
253617
|
-
|
|
253618
|
-
query = JSON.parse(q13);
|
|
253619
|
-
} catch {
|
|
253620
|
-
res.status(400).json({ error: "Invalid query parameter 'q'" });
|
|
253621
|
-
return;
|
|
253622
|
-
}
|
|
253623
|
-
}
|
|
253624
|
-
let cursor3 = collection.findAsync(query);
|
|
253625
|
-
const sortObj = parseSort(sort);
|
|
253626
|
-
if (sortObj) {
|
|
253627
|
-
cursor3 = cursor3.sort(sortObj);
|
|
253628
|
-
}
|
|
253629
|
-
if (skip2) {
|
|
253630
|
-
const skipNum = Number.parseInt(skip2, 10);
|
|
253631
|
-
if (!Number.isNaN(skipNum)) {
|
|
253632
|
-
cursor3 = cursor3.skip(skipNum);
|
|
253633
|
-
}
|
|
253974
|
+
const schema10 = db2.getSchema(entityName);
|
|
253975
|
+
if (schema10?.rls?.read === false) {
|
|
253976
|
+
res.json([]);
|
|
253977
|
+
return;
|
|
253634
253978
|
}
|
|
253635
|
-
|
|
253636
|
-
|
|
253637
|
-
|
|
253638
|
-
cursor3 = cursor3.limit(limitNum);
|
|
253639
|
-
}
|
|
253979
|
+
let results = stripInternalFields(await queryEntity(collection, req.query));
|
|
253980
|
+
if (schema10?.rls?.read && schema10.rls.read !== true) {
|
|
253981
|
+
results = results.filter((doc2) => checkRLS(schema10.rls.read, doc2, currentUser));
|
|
253640
253982
|
}
|
|
253641
|
-
|
|
253642
|
-
|
|
253643
|
-
cursor3 = cursor3.projection(projection);
|
|
253983
|
+
if (schema10) {
|
|
253984
|
+
results = results.map((doc2) => applyFLS(doc2, schema10, currentUser, "read"));
|
|
253644
253985
|
}
|
|
253645
|
-
|
|
253646
|
-
res.json(stripInternalFields(docs));
|
|
253986
|
+
res.json(results);
|
|
253647
253987
|
} catch (error48) {
|
|
253648
|
-
|
|
253649
|
-
|
|
253988
|
+
if (error48 instanceof InvalidInputError) {
|
|
253989
|
+
res.status(400).json({ error: error48.message });
|
|
253990
|
+
} else {
|
|
253991
|
+
logger2.error(`Error in GET /${entityName}:`, error48);
|
|
253992
|
+
res.status(500).json({ error: "Internal server error" });
|
|
253993
|
+
}
|
|
253650
253994
|
}
|
|
253651
253995
|
}));
|
|
253652
|
-
router.post("/:entityName", parseBody, withCollection(async (req, res, collection) => {
|
|
253996
|
+
router.post("/:entityName", parseBody, withCollection(async (req, res, collection, currentUser) => {
|
|
253653
253997
|
const { appId, entityName } = req.params;
|
|
253654
253998
|
try {
|
|
253655
253999
|
const now = new Date().toISOString();
|
|
253656
254000
|
const { _id, ...body } = req.body;
|
|
253657
|
-
const
|
|
254001
|
+
const schema10 = db2.getSchema(entityName);
|
|
254002
|
+
if (!checkRLS(schema10?.rls?.create, {
|
|
254003
|
+
...body,
|
|
254004
|
+
created_by: currentUser?.email,
|
|
254005
|
+
created_by_id: currentUser?.id
|
|
254006
|
+
}, currentUser)) {
|
|
254007
|
+
res.status(403).json({ error: "Permission denied" });
|
|
254008
|
+
return;
|
|
254009
|
+
}
|
|
254010
|
+
let filteredBody = db2.prepareRecord(entityName, body);
|
|
254011
|
+
if (schema10) {
|
|
254012
|
+
filteredBody = applyFLS(filteredBody, schema10, currentUser, "write");
|
|
254013
|
+
}
|
|
253658
254014
|
db2.validate(entityName, filteredBody);
|
|
253659
254015
|
const record2 = {
|
|
253660
254016
|
...filteredBody,
|
|
253661
254017
|
id: nanoid3(),
|
|
254018
|
+
created_by: currentUser?.email,
|
|
254019
|
+
created_by_id: currentUser?.id,
|
|
253662
254020
|
created_date: now,
|
|
253663
254021
|
updated_date: now
|
|
253664
254022
|
};
|
|
@@ -253674,7 +254032,7 @@ async function createEntityRoutes(db2, logger2, broadcast) {
|
|
|
253674
254032
|
res.status(500).json({ error: "Internal server error" });
|
|
253675
254033
|
}
|
|
253676
254034
|
}));
|
|
253677
|
-
router.post("/:entityName/bulk", parseBody, withCollection(async (req, res, collection) => {
|
|
254035
|
+
router.post("/:entityName/bulk", parseBody, withCollection(async (req, res, collection, currentUser) => {
|
|
253678
254036
|
const { appId, entityName } = req.params;
|
|
253679
254037
|
if (!Array.isArray(req.body)) {
|
|
253680
254038
|
res.status(400).json({ error: "Request body must be an array" });
|
|
@@ -253682,13 +254040,27 @@ async function createEntityRoutes(db2, logger2, broadcast) {
|
|
|
253682
254040
|
}
|
|
253683
254041
|
try {
|
|
253684
254042
|
const now = new Date().toISOString();
|
|
254043
|
+
const schema10 = db2.getSchema(entityName);
|
|
253685
254044
|
const records = [];
|
|
253686
254045
|
for (const record2 of req.body) {
|
|
253687
|
-
|
|
254046
|
+
if (!checkRLS(schema10?.rls?.create, {
|
|
254047
|
+
...record2,
|
|
254048
|
+
created_by: currentUser?.email,
|
|
254049
|
+
created_by_id: currentUser?.id
|
|
254050
|
+
}, currentUser)) {
|
|
254051
|
+
res.status(403).json({ error: "Permission denied" });
|
|
254052
|
+
return;
|
|
254053
|
+
}
|
|
254054
|
+
let filteredRecord = db2.prepareRecord(entityName, record2);
|
|
254055
|
+
if (schema10) {
|
|
254056
|
+
filteredRecord = applyFLS(filteredRecord, schema10, currentUser, "write");
|
|
254057
|
+
}
|
|
253688
254058
|
db2.validate(entityName, filteredRecord);
|
|
253689
254059
|
records.push({
|
|
253690
254060
|
...filteredRecord,
|
|
253691
254061
|
id: nanoid3(),
|
|
254062
|
+
created_by: currentUser?.email,
|
|
254063
|
+
created_by_id: currentUser?.id,
|
|
253692
254064
|
created_date: now,
|
|
253693
254065
|
updated_date: now
|
|
253694
254066
|
});
|
|
@@ -253705,11 +254077,26 @@ async function createEntityRoutes(db2, logger2, broadcast) {
|
|
|
253705
254077
|
res.status(500).json({ error: "Internal server error" });
|
|
253706
254078
|
}
|
|
253707
254079
|
}));
|
|
253708
|
-
router.put("/:entityName/:id", parseBody, withCollection(async (req, res, collection) => {
|
|
254080
|
+
router.put("/:entityName/:id", parseBody, withCollection(async (req, res, collection, currentUser) => {
|
|
253709
254081
|
const { appId, entityName, id: id2 } = req.params;
|
|
253710
254082
|
const { id: _id, created_date: _created_date, ...body } = req.body;
|
|
253711
254083
|
try {
|
|
253712
|
-
const
|
|
254084
|
+
const schema10 = db2.getSchema(entityName);
|
|
254085
|
+
if (schema10?.rls?.update !== undefined) {
|
|
254086
|
+
const existing = await collection.findOneAsync({ id: id2 });
|
|
254087
|
+
if (!existing) {
|
|
254088
|
+
res.status(404).json({ error: `Record with id "${id2}" not found` });
|
|
254089
|
+
return;
|
|
254090
|
+
}
|
|
254091
|
+
if (!checkRLS(schema10.rls.update, existing, currentUser)) {
|
|
254092
|
+
res.status(403).json({ error: "Permission denied" });
|
|
254093
|
+
return;
|
|
254094
|
+
}
|
|
254095
|
+
}
|
|
254096
|
+
let filteredBody = db2.prepareRecord(entityName, body, true);
|
|
254097
|
+
if (schema10) {
|
|
254098
|
+
filteredBody = applyFLS(filteredBody, schema10, currentUser, "write");
|
|
254099
|
+
}
|
|
253713
254100
|
db2.validate(entityName, filteredBody, true);
|
|
253714
254101
|
const updateData = {
|
|
253715
254102
|
...filteredBody,
|
|
@@ -253732,30 +254119,48 @@ async function createEntityRoutes(db2, logger2, broadcast) {
|
|
|
253732
254119
|
res.status(500).json({ error: "Internal server error" });
|
|
253733
254120
|
}
|
|
253734
254121
|
}));
|
|
253735
|
-
router.delete("/:entityName/:id", withCollection(async (req, res, collection) => {
|
|
254122
|
+
router.delete("/:entityName/:id", withCollection(async (req, res, collection, currentUser) => {
|
|
253736
254123
|
const { appId, entityName, id: id2 } = req.params;
|
|
253737
254124
|
try {
|
|
253738
254125
|
const doc2 = await collection.findOneAsync({ id: id2 });
|
|
253739
|
-
|
|
253740
|
-
if (numRemoved === 0) {
|
|
254126
|
+
if (!doc2) {
|
|
253741
254127
|
res.status(404).json({ error: `Record with id "${id2}" not found` });
|
|
253742
254128
|
return;
|
|
253743
254129
|
}
|
|
253744
|
-
|
|
253745
|
-
|
|
254130
|
+
const schema10 = db2.getSchema(entityName);
|
|
254131
|
+
if (!checkRLS(schema10?.rls?.delete, doc2, currentUser)) {
|
|
254132
|
+
res.status(403).json({ error: "Permission denied" });
|
|
254133
|
+
return;
|
|
253746
254134
|
}
|
|
254135
|
+
await collection.removeAsync({ id: id2 }, { multi: false });
|
|
254136
|
+
emit(appId, entityName, "delete", stripInternalFields(doc2));
|
|
253747
254137
|
res.json({ success: true });
|
|
253748
254138
|
} catch (error48) {
|
|
253749
254139
|
logger2.error(`Error in DELETE /${entityName}/${id2}:`, error48);
|
|
253750
254140
|
res.status(500).json({ error: "Internal server error" });
|
|
253751
254141
|
}
|
|
253752
254142
|
}));
|
|
253753
|
-
router.delete("/:entityName", parseBody, withCollection(async (req, res, collection) => {
|
|
254143
|
+
router.delete("/:entityName", parseBody, withCollection(async (req, res, collection, currentUser) => {
|
|
253754
254144
|
const { entityName } = req.params;
|
|
253755
254145
|
try {
|
|
253756
254146
|
const query = req.body || {};
|
|
253757
|
-
const
|
|
253758
|
-
|
|
254147
|
+
const schema10 = db2.getSchema(entityName);
|
|
254148
|
+
const rlsDelete = schema10?.rls?.delete;
|
|
254149
|
+
if (rlsDelete !== undefined && rlsDelete !== true) {
|
|
254150
|
+
if (rlsDelete === false) {
|
|
254151
|
+
res.status(403).json({ error: "Permission denied" });
|
|
254152
|
+
return;
|
|
254153
|
+
}
|
|
254154
|
+
const docs = await collection.findAsync(query);
|
|
254155
|
+
const allowedIds = docs.filter((doc2) => checkRLS(rlsDelete, doc2, currentUser)).map((doc2) => doc2.id);
|
|
254156
|
+
const numRemoved = await collection.removeAsync({ id: { $in: allowedIds } }, { multi: true });
|
|
254157
|
+
res.json({ success: true, deleted: numRemoved });
|
|
254158
|
+
} else {
|
|
254159
|
+
const numRemoved = await collection.removeAsync(query, {
|
|
254160
|
+
multi: true
|
|
254161
|
+
});
|
|
254162
|
+
res.json({ success: true, deleted: numRemoved });
|
|
254163
|
+
}
|
|
253759
254164
|
} catch (error48) {
|
|
253760
254165
|
logger2.error(`Error in DELETE /${entityName}:`, error48);
|
|
253761
254166
|
res.status(500).json({ error: "Internal server error" });
|
|
@@ -253765,7 +254170,7 @@ async function createEntityRoutes(db2, logger2, broadcast) {
|
|
|
253765
254170
|
}
|
|
253766
254171
|
|
|
253767
254172
|
// src/cli/dev/dev-server/routes/integrations.ts
|
|
253768
|
-
var
|
|
254173
|
+
var import_express5 = __toESM(require_express(), 1);
|
|
253769
254174
|
var import_multer = __toESM(require_multer(), 1);
|
|
253770
254175
|
import { createHash, randomUUID as randomUUID4 } from "node:crypto";
|
|
253771
254176
|
import fs28 from "node:fs";
|
|
@@ -253774,8 +254179,8 @@ function createFileToken(fileUri) {
|
|
|
253774
254179
|
return createHash("sha256").update(fileUri).digest("hex");
|
|
253775
254180
|
}
|
|
253776
254181
|
function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger2) {
|
|
253777
|
-
const router =
|
|
253778
|
-
const parseBody =
|
|
254182
|
+
const router = import_express5.Router({ mergeParams: true });
|
|
254183
|
+
const parseBody = import_express5.json();
|
|
253779
254184
|
const privateFilesDir = path18.join(mediaFilesDir, "private");
|
|
253780
254185
|
fs28.mkdirSync(mediaFilesDir, { recursive: true });
|
|
253781
254186
|
fs28.mkdirSync(privateFilesDir, { recursive: true });
|
|
@@ -253845,7 +254250,7 @@ function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger2) {
|
|
|
253845
254250
|
return router;
|
|
253846
254251
|
}
|
|
253847
254252
|
function createCustomIntegrationRoutes(remoteProxy, logger2) {
|
|
253848
|
-
const router =
|
|
254253
|
+
const router = import_express5.Router({ mergeParams: true });
|
|
253849
254254
|
router.post("/:slug/:operationId", (req, res, next) => {
|
|
253850
254255
|
logger2.warn(`"${req.originalUrl}" is not supported in local development, passing call to production`);
|
|
253851
254256
|
req.url = req.originalUrl;
|
|
@@ -255558,7 +255963,7 @@ async function createDevServer(options8) {
|
|
|
255558
255963
|
const port = userPort ?? await getPorts({ port: DEFAULT_PORT });
|
|
255559
255964
|
const baseUrl = `http://localhost:${port}`;
|
|
255560
255965
|
const { functions, entities, project: project2 } = await options8.loadResources();
|
|
255561
|
-
const app =
|
|
255966
|
+
const app = import_express6.default();
|
|
255562
255967
|
const remoteProxy = import_http_proxy_middleware2.createProxyMiddleware({
|
|
255563
255968
|
target: BASE44_APP_URL,
|
|
255564
255969
|
changeOrigin: true
|
|
@@ -255590,6 +255995,8 @@ async function createDevServer(options8) {
|
|
|
255590
255995
|
let emitEntityEvent = () => {};
|
|
255591
255996
|
const entityRoutes = await createEntityRoutes(db2, devLogger, (...args) => emitEntityEvent(...args));
|
|
255592
255997
|
app.use("/api/apps/:appId/entities", entityRoutes);
|
|
255998
|
+
const authRouter = createAuthRouter(db2, devLogger);
|
|
255999
|
+
app.use("/api/apps/:appId/auth", authRouter);
|
|
255593
256000
|
const { path: mediaFilesDir } = await $dir();
|
|
255594
256001
|
app.use("/media/private/:fileUri", (req, res, next) => {
|
|
255595
256002
|
const { fileUri } = req.params;
|
|
@@ -255609,13 +256016,15 @@ async function createDevServer(options8) {
|
|
|
255609
256016
|
}
|
|
255610
256017
|
next();
|
|
255611
256018
|
});
|
|
255612
|
-
app.use("/media",
|
|
256019
|
+
app.use("/media", import_express6.default.static(mediaFilesDir));
|
|
255613
256020
|
const integrationRoutes = createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, devLogger);
|
|
255614
256021
|
app.use("/api/apps/:appId/integration-endpoints", integrationRoutes);
|
|
255615
256022
|
const customIntegrationRoutes = createCustomIntegrationRoutes(remoteProxy, devLogger);
|
|
255616
256023
|
app.use("/api/apps/:appId/integrations/custom", customIntegrationRoutes);
|
|
255617
256024
|
app.use((req, res, next) => {
|
|
255618
|
-
|
|
256025
|
+
if (!req.originalUrl.endsWith("analytics/track/batch")) {
|
|
256026
|
+
devLogger.warn(`"${req.originalUrl}" is not supported in local development, passing call to production`);
|
|
256027
|
+
}
|
|
255619
256028
|
remoteProxy(req, res, next);
|
|
255620
256029
|
});
|
|
255621
256030
|
const server = await new Promise((resolve8, reject) => {
|
|
@@ -255686,6 +256095,7 @@ async function devAction({ log }, options8) {
|
|
|
255686
256095
|
const { port: resolvedPort } = await createDevServer({
|
|
255687
256096
|
log,
|
|
255688
256097
|
port,
|
|
256098
|
+
cwd: process21.cwd(),
|
|
255689
256099
|
denoWrapperPath: getDenoWrapperPath(),
|
|
255690
256100
|
loadResources: async () => {
|
|
255691
256101
|
const { functions, entities, project: project2 } = await readProjectConfig();
|
|
@@ -260193,4 +260603,4 @@ export {
|
|
|
260193
260603
|
CLIExitError
|
|
260194
260604
|
};
|
|
260195
260605
|
|
|
260196
|
-
//# debugId=
|
|
260606
|
+
//# debugId=FF5639434B8FD38C64756E2164756E21
|