@base44-preview/cli 0.0.45-pr.406.7acd6ec → 0.0.45-pr.419.e270ff0
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/README.md +5 -1
- package/dist/assets/deno-runtime/main.ts +72 -0
- package/dist/cli/index.js +33 -123
- package/dist/cli/index.js.map +7 -10
- package/package.json +1 -1
- package/dist/assets/deno-runtime/main.js +0 -31
- package/dist/assets/deno-runtime/main.js.map +0 -10
package/README.md
CHANGED
|
@@ -53,10 +53,14 @@ The CLI will guide you through project setup. For step-by-step tutorials, see th
|
|
|
53
53
|
| [`whoami`](https://docs.base44.com/developers/references/cli/commands/whoami) | Display the current authenticated user |
|
|
54
54
|
| [`agents pull`](https://docs.base44.com/developers/references/cli/commands/agents-pull) | Pull agents from Base44 to local files |
|
|
55
55
|
| [`agents push`](https://docs.base44.com/developers/references/cli/commands/agents-push) | Push local agents to Base44 |
|
|
56
|
+
| [`connectors list-available`](https://docs.base44.com/developers/references/cli/commands/connectors-list-available) | List all available integration types |
|
|
56
57
|
| [`connectors pull`](https://docs.base44.com/developers/references/cli/commands/connectors-pull) | Pull connectors from Base44 to local files |
|
|
57
58
|
| [`connectors push`](https://docs.base44.com/developers/references/cli/commands/connectors-push) | Push local connectors to Base44 |
|
|
58
59
|
| [`entities push`](https://docs.base44.com/developers/references/cli/commands/entities-push) | Push local entities to Base44 |
|
|
59
|
-
|
|
|
60
|
+
| `functions delete` | Delete deployed functions |
|
|
61
|
+
| [`functions deploy`](https://docs.base44.com/developers/references/cli/commands/functions-deploy) | Deploy functions to Base44 |
|
|
62
|
+
| `functions list` | List all deployed functions |
|
|
63
|
+
| `functions pull` | Pull deployed functions from Base44 |
|
|
60
64
|
| [`secrets list`](https://docs.base44.com/developers/references/cli/commands/secrets-list) | List project secret names |
|
|
61
65
|
| [`secrets set`](https://docs.base44.com/developers/references/cli/commands/secrets-set) | Set one or more project secrets |
|
|
62
66
|
| [`secrets delete`](https://docs.base44.com/developers/references/cli/commands/secrets-delete) | Delete a project secret |
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deno Function Wrapper
|
|
3
|
+
*
|
|
4
|
+
* This script is executed by Deno to run user functions.
|
|
5
|
+
* It patches Deno.serve to inject a dynamic port before importing the user's function.
|
|
6
|
+
*
|
|
7
|
+
* Environment variables:
|
|
8
|
+
* - FUNCTION_PATH: Absolute path to the user's function entry file
|
|
9
|
+
* - FUNCTION_PORT: Port number for the function to listen on
|
|
10
|
+
* - FUNCTION_NAME: Name of the function (for logging)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Make this file a module for top-level await support
|
|
14
|
+
export {};
|
|
15
|
+
|
|
16
|
+
const functionPath = Deno.env.get("FUNCTION_PATH");
|
|
17
|
+
const port = parseInt(Deno.env.get("FUNCTION_PORT") || "8000", 10);
|
|
18
|
+
const functionName = Deno.env.get("FUNCTION_NAME") || "unknown";
|
|
19
|
+
|
|
20
|
+
if (!functionPath) {
|
|
21
|
+
console.error("[wrapper] FUNCTION_PATH environment variable is required");
|
|
22
|
+
Deno.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Store the original Deno.serve
|
|
26
|
+
const originalServe = Deno.serve.bind(Deno);
|
|
27
|
+
|
|
28
|
+
// Patch Deno.serve to inject our port and add onListen callback
|
|
29
|
+
// @ts-expect-error - We're intentionally overriding Deno.serve
|
|
30
|
+
Deno.serve = (
|
|
31
|
+
optionsOrHandler:
|
|
32
|
+
| Deno.ServeOptions
|
|
33
|
+
| Deno.ServeHandler
|
|
34
|
+
| (Deno.ServeOptions & { handler: Deno.ServeHandler }),
|
|
35
|
+
maybeHandler?: Deno.ServeHandler,
|
|
36
|
+
): Deno.HttpServer<Deno.NetAddr> => {
|
|
37
|
+
const onListen = () => {
|
|
38
|
+
// This message is used by FunctionManager to detect when the function is ready
|
|
39
|
+
console.log(`[${functionName}] Listening on http://localhost:${port}`);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Handle the different Deno.serve signatures:
|
|
43
|
+
// 1. Deno.serve(handler)
|
|
44
|
+
// 2. Deno.serve(options, handler)
|
|
45
|
+
// 3. Deno.serve({ ...options, handler })
|
|
46
|
+
if (typeof optionsOrHandler === "function") {
|
|
47
|
+
// Signature: Deno.serve(handler)
|
|
48
|
+
return originalServe({ port, onListen }, optionsOrHandler);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (maybeHandler) {
|
|
52
|
+
// Signature: Deno.serve(options, handler)
|
|
53
|
+
return originalServe({ ...optionsOrHandler, port, onListen }, maybeHandler);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Signature: Deno.serve({ ...options, handler })
|
|
57
|
+
const options = optionsOrHandler as Deno.ServeOptions & {
|
|
58
|
+
handler: Deno.ServeHandler;
|
|
59
|
+
};
|
|
60
|
+
return originalServe({ ...options, port, onListen });
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
console.log(`[${functionName}] Starting function from ${functionPath}`);
|
|
64
|
+
|
|
65
|
+
// Dynamically import the user's function
|
|
66
|
+
// The function will call Deno.serve which is now patched to use our port
|
|
67
|
+
try {
|
|
68
|
+
await import(functionPath);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error(`[${functionName}] Failed to load function:`, error);
|
|
71
|
+
Deno.exit(1);
|
|
72
|
+
}
|
package/dist/cli/index.js
CHANGED
|
@@ -238807,7 +238807,7 @@ function getTemplatesIndexPath() {
|
|
|
238807
238807
|
return join8(ASSETS_DIR, "templates", "templates.json");
|
|
238808
238808
|
}
|
|
238809
238809
|
function getDenoWrapperPath() {
|
|
238810
|
-
return join8(ASSETS_DIR, "deno-runtime", "main.
|
|
238810
|
+
return join8(ASSETS_DIR, "deno-runtime", "main.ts");
|
|
238811
238811
|
}
|
|
238812
238812
|
function ensureNpmAssets(sourceDir) {
|
|
238813
238813
|
if (existsSync(ASSETS_DIR))
|
|
@@ -248819,7 +248819,7 @@ function getTypesCommand(context) {
|
|
|
248819
248819
|
// src/cli/dev/dev-server/main.ts
|
|
248820
248820
|
import { dirname as dirname14, join as join20 } from "node:path";
|
|
248821
248821
|
var import_cors = __toESM(require_lib4(), 1);
|
|
248822
|
-
var
|
|
248822
|
+
var import_express4 = __toESM(require_express(), 1);
|
|
248823
248823
|
|
|
248824
248824
|
// ../../node_modules/get-port/index.js
|
|
248825
248825
|
import net from "node:net";
|
|
@@ -249323,47 +249323,18 @@ class Validator {
|
|
|
249323
249323
|
}
|
|
249324
249324
|
|
|
249325
249325
|
// src/cli/dev/dev-server/db/database.ts
|
|
249326
|
-
var USER_COLLECTION = "user";
|
|
249327
|
-
|
|
249328
249326
|
class Database {
|
|
249329
249327
|
collections = new Map;
|
|
249330
249328
|
schemas = new Map;
|
|
249331
249329
|
validator = new Validator;
|
|
249332
249330
|
load(entities) {
|
|
249333
|
-
this.collections.set(USER_COLLECTION, new import_nedb.default);
|
|
249334
249331
|
for (const entity2 of entities) {
|
|
249335
|
-
|
|
249336
|
-
this.
|
|
249337
|
-
const clonedEntity = structuredClone(entity2);
|
|
249338
|
-
if (entityName === USER_COLLECTION) {
|
|
249339
|
-
["full_name", "email"].forEach((predefinedField) => {
|
|
249340
|
-
if (predefinedField in clonedEntity.properties) {
|
|
249341
|
-
throw new Error(`Error syncing entities: Invalid User schema: User schema cannot contain base fields: ${predefinedField}. These fields are built-in and managed by the system.`);
|
|
249342
|
-
}
|
|
249343
|
-
});
|
|
249344
|
-
clonedEntity.properties.full_name = { type: "string" };
|
|
249345
|
-
clonedEntity.properties.email = { type: "string" };
|
|
249346
|
-
clonedEntity.properties.role = { type: "string" };
|
|
249347
|
-
}
|
|
249348
|
-
this.schemas.set(entityName, clonedEntity);
|
|
249349
|
-
}
|
|
249350
|
-
if (!this.schemas.has(USER_COLLECTION)) {
|
|
249351
|
-
this.schemas.set(USER_COLLECTION, {
|
|
249352
|
-
name: "User",
|
|
249353
|
-
type: "object",
|
|
249354
|
-
properties: {
|
|
249355
|
-
full_name: { type: "string" },
|
|
249356
|
-
email: { type: "string" },
|
|
249357
|
-
role: { type: "string" }
|
|
249358
|
-
}
|
|
249359
|
-
});
|
|
249332
|
+
this.collections.set(entity2.name, new import_nedb.default);
|
|
249333
|
+
this.schemas.set(entity2.name, entity2);
|
|
249360
249334
|
}
|
|
249361
249335
|
}
|
|
249362
|
-
hasCollection(name2) {
|
|
249363
|
-
return this.collections.has(this.normalizeName(name2));
|
|
249364
|
-
}
|
|
249365
249336
|
getCollection(name2) {
|
|
249366
|
-
return this.collections.get(
|
|
249337
|
+
return this.collections.get(name2);
|
|
249367
249338
|
}
|
|
249368
249339
|
getCollectionNames() {
|
|
249369
249340
|
return Array.from(this.collections.keys());
|
|
@@ -249376,14 +249347,14 @@ class Database {
|
|
|
249376
249347
|
this.schemas.clear();
|
|
249377
249348
|
}
|
|
249378
249349
|
validate(entityName, record2, partial2 = false) {
|
|
249379
|
-
const schema9 = this.schemas.get(
|
|
249350
|
+
const schema9 = this.schemas.get(entityName);
|
|
249380
249351
|
if (!schema9) {
|
|
249381
249352
|
throw new Error(`Entity "${entityName}" not found`);
|
|
249382
249353
|
}
|
|
249383
249354
|
return this.validator.validate(record2, schema9, partial2);
|
|
249384
249355
|
}
|
|
249385
249356
|
prepareRecord(entityName, record2, partial2 = false) {
|
|
249386
|
-
const schema9 = this.schemas.get(
|
|
249357
|
+
const schema9 = this.schemas.get(entityName);
|
|
249387
249358
|
if (!schema9) {
|
|
249388
249359
|
throw new Error(`Entity "${entityName}" not found`);
|
|
249389
249360
|
}
|
|
@@ -249393,9 +249364,6 @@ class Database {
|
|
|
249393
249364
|
}
|
|
249394
249365
|
return this.validator.applyDefaults(filteredRecord, schema9);
|
|
249395
249366
|
}
|
|
249396
|
-
normalizeName(entityName) {
|
|
249397
|
-
return entityName.toLowerCase();
|
|
249398
|
-
}
|
|
249399
249367
|
}
|
|
249400
249368
|
|
|
249401
249369
|
// ../../node_modules/socket.io/wrapper.mjs
|
|
@@ -249430,8 +249398,8 @@ function broadcastEntityEvent(io6, appId, entityName, event) {
|
|
|
249430
249398
|
});
|
|
249431
249399
|
}
|
|
249432
249400
|
|
|
249433
|
-
// src/cli/dev/dev-server/routes/entities
|
|
249434
|
-
var
|
|
249401
|
+
// src/cli/dev/dev-server/routes/entities.ts
|
|
249402
|
+
var import_express2 = __toESM(require_express(), 1);
|
|
249435
249403
|
|
|
249436
249404
|
// ../../node_modules/nanoid/index.js
|
|
249437
249405
|
import { webcrypto as crypto } from "node:crypto";
|
|
@@ -249463,53 +249431,7 @@ function nanoid3(size = 21) {
|
|
|
249463
249431
|
return id2;
|
|
249464
249432
|
}
|
|
249465
249433
|
|
|
249466
|
-
// src/cli/dev/dev-server/routes/entities
|
|
249467
|
-
var import_express2 = __toESM(require_express(), 1);
|
|
249468
|
-
|
|
249469
|
-
// src/cli/dev/dev-server/routes/entities/utils.ts
|
|
249470
|
-
function stripInternalFields(doc2) {
|
|
249471
|
-
if (Array.isArray(doc2)) {
|
|
249472
|
-
return doc2.map((d5) => stripInternalFields(d5));
|
|
249473
|
-
}
|
|
249474
|
-
const { _id, ...rest } = doc2;
|
|
249475
|
-
return rest;
|
|
249476
|
-
}
|
|
249477
|
-
|
|
249478
|
-
// src/cli/dev/dev-server/routes/entities/entities-user-router.ts
|
|
249479
|
-
async function createUserRouter(db2) {
|
|
249480
|
-
const userInfo = await readAuth();
|
|
249481
|
-
const meEntity = await db2.getCollection("User")?.findOneAsync({ email: userInfo.email });
|
|
249482
|
-
let idMe = meEntity?.id;
|
|
249483
|
-
if (!idMe) {
|
|
249484
|
-
const now = new Date().toISOString().replace("Z", "000");
|
|
249485
|
-
idMe = nanoid3();
|
|
249486
|
-
await db2.getCollection("User")?.insertAsync({
|
|
249487
|
-
id: idMe,
|
|
249488
|
-
email: userInfo.email,
|
|
249489
|
-
full_name: userInfo.name,
|
|
249490
|
-
is_service: false,
|
|
249491
|
-
is_verified: true,
|
|
249492
|
-
disabled: null,
|
|
249493
|
-
role: "admin",
|
|
249494
|
-
collaborator_role: "editor",
|
|
249495
|
-
created_date: now,
|
|
249496
|
-
updated_date: now
|
|
249497
|
-
});
|
|
249498
|
-
}
|
|
249499
|
-
const router = import_express2.Router({ mergeParams: true });
|
|
249500
|
-
router.get("/:id", async (req, res) => {
|
|
249501
|
-
const id2 = req.params.id === "me" ? idMe : req.params.id;
|
|
249502
|
-
const result = await db2.getCollection("User")?.findOneAsync({ id: id2 });
|
|
249503
|
-
if (!result) {
|
|
249504
|
-
res.status(404).json({ error: `User with id "${req.params.id}" not found` });
|
|
249505
|
-
return;
|
|
249506
|
-
}
|
|
249507
|
-
res.json(stripInternalFields(result));
|
|
249508
|
-
});
|
|
249509
|
-
return router;
|
|
249510
|
-
}
|
|
249511
|
-
|
|
249512
|
-
// src/cli/dev/dev-server/routes/entities/entities-router.ts
|
|
249434
|
+
// src/cli/dev/dev-server/routes/entities.ts
|
|
249513
249435
|
function parseSort(sort) {
|
|
249514
249436
|
if (!sort) {
|
|
249515
249437
|
return;
|
|
@@ -249532,9 +249454,16 @@ function parseFields(fields) {
|
|
|
249532
249454
|
}
|
|
249533
249455
|
return Object.keys(projection).length > 0 ? projection : undefined;
|
|
249534
249456
|
}
|
|
249535
|
-
|
|
249536
|
-
|
|
249537
|
-
|
|
249457
|
+
function stripInternalFields(doc2) {
|
|
249458
|
+
if (Array.isArray(doc2)) {
|
|
249459
|
+
return doc2.map((d5) => stripInternalFields(d5));
|
|
249460
|
+
}
|
|
249461
|
+
const { _id, ...rest } = doc2;
|
|
249462
|
+
return rest;
|
|
249463
|
+
}
|
|
249464
|
+
function createEntityRoutes(db2, logger, remoteProxy, broadcast) {
|
|
249465
|
+
const router = import_express2.Router({ mergeParams: true });
|
|
249466
|
+
const parseBody = import_express2.json();
|
|
249538
249467
|
function withCollection(handler) {
|
|
249539
249468
|
return async (req, res) => {
|
|
249540
249469
|
const collection = db2.getCollection(req.params.entityName);
|
|
@@ -249560,8 +249489,11 @@ async function createEntityRoutes(db2, logger, broadcast) {
|
|
|
249560
249489
|
}
|
|
249561
249490
|
broadcast(appId, entityName, createData(data));
|
|
249562
249491
|
}
|
|
249563
|
-
|
|
249564
|
-
|
|
249492
|
+
router.get("/User/:id", (req, res, next) => {
|
|
249493
|
+
logger.warn(`"${req.originalUrl}" is not supported in local development, passing call to production`);
|
|
249494
|
+
req.url = req.originalUrl;
|
|
249495
|
+
remoteProxy(req, res, next);
|
|
249496
|
+
});
|
|
249565
249497
|
router.get("/:entityName/:id", withCollection(async (req, res, collection) => {
|
|
249566
249498
|
const { entityName, id: id2 } = req.params;
|
|
249567
249499
|
try {
|
|
@@ -249733,7 +249665,7 @@ async function createEntityRoutes(db2, logger, broadcast) {
|
|
|
249733
249665
|
}
|
|
249734
249666
|
|
|
249735
249667
|
// src/cli/dev/dev-server/routes/integrations.ts
|
|
249736
|
-
var
|
|
249668
|
+
var import_express3 = __toESM(require_express(), 1);
|
|
249737
249669
|
var import_multer = __toESM(require_multer(), 1);
|
|
249738
249670
|
import { createHash, randomUUID as randomUUID4 } from "node:crypto";
|
|
249739
249671
|
import fs28 from "node:fs";
|
|
@@ -249742,8 +249674,8 @@ function createFileToken(fileUri) {
|
|
|
249742
249674
|
return createHash("sha256").update(fileUri).digest("hex");
|
|
249743
249675
|
}
|
|
249744
249676
|
function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger) {
|
|
249745
|
-
const router =
|
|
249746
|
-
const parseBody =
|
|
249677
|
+
const router = import_express3.Router({ mergeParams: true });
|
|
249678
|
+
const parseBody = import_express3.json();
|
|
249747
249679
|
const privateFilesDir = path18.join(mediaFilesDir, "private");
|
|
249748
249680
|
fs28.mkdirSync(mediaFilesDir, { recursive: true });
|
|
249749
249681
|
fs28.mkdirSync(privateFilesDir, { recursive: true });
|
|
@@ -249813,7 +249745,7 @@ function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger) {
|
|
|
249813
249745
|
return router;
|
|
249814
249746
|
}
|
|
249815
249747
|
function createCustomIntegrationRoutes(remoteProxy, logger) {
|
|
249816
|
-
const router =
|
|
249748
|
+
const router = import_express3.Router({ mergeParams: true });
|
|
249817
249749
|
router.post("/:slug/:operationId", (req, res, next) => {
|
|
249818
249750
|
logger.warn(`"${req.originalUrl}" is not supported in local development, passing call to production`);
|
|
249819
249751
|
req.url = req.originalUrl;
|
|
@@ -249822,18 +249754,6 @@ function createCustomIntegrationRoutes(remoteProxy, logger) {
|
|
|
249822
249754
|
return router;
|
|
249823
249755
|
}
|
|
249824
249756
|
|
|
249825
|
-
// src/cli/dev/dev-server/routes/users.ts
|
|
249826
|
-
var import_express5 = __toESM(require_express(), 1);
|
|
249827
|
-
function createUsersRoutes() {
|
|
249828
|
-
const router = import_express5.Router({ mergeParams: true });
|
|
249829
|
-
const parseBody = import_express5.json();
|
|
249830
|
-
router.post("/invite-user", parseBody, (req, _res, next) => {
|
|
249831
|
-
console.log("invite-user", req.body);
|
|
249832
|
-
next();
|
|
249833
|
-
});
|
|
249834
|
-
return router;
|
|
249835
|
-
}
|
|
249836
|
-
|
|
249837
249757
|
// src/cli/dev/dev-server/watcher.ts
|
|
249838
249758
|
import { EventEmitter as EventEmitter4 } from "node:events";
|
|
249839
249759
|
import { relative as relative6 } from "node:path";
|
|
@@ -251538,7 +251458,7 @@ async function createDevServer(options8) {
|
|
|
251538
251458
|
const port = userPort ?? await getPorts({ port: DEFAULT_PORT });
|
|
251539
251459
|
const baseUrl = `http://localhost:${port}`;
|
|
251540
251460
|
const { functions, entities, project: project2 } = await options8.loadResources();
|
|
251541
|
-
const app =
|
|
251461
|
+
const app = import_express4.default();
|
|
251542
251462
|
const remoteProxy = import_http_proxy_middleware2.createProxyMiddleware({
|
|
251543
251463
|
target: BASE44_APP_URL,
|
|
251544
251464
|
changeOrigin: true
|
|
@@ -251555,17 +251475,7 @@ async function createDevServer(options8) {
|
|
|
251555
251475
|
}
|
|
251556
251476
|
next();
|
|
251557
251477
|
});
|
|
251558
|
-
app.use((req, res, next) => {
|
|
251559
|
-
const auth2 = req.headers.authorization;
|
|
251560
|
-
if (!auth2 || !auth2.startsWith("Bearer ")) {
|
|
251561
|
-
res.status(401).json({ error: "Unauthorized" });
|
|
251562
|
-
return;
|
|
251563
|
-
}
|
|
251564
|
-
next();
|
|
251565
|
-
});
|
|
251566
251478
|
const devLogger = createDevLogger();
|
|
251567
|
-
const usersRoutes = createUsersRoutes();
|
|
251568
|
-
app.use("/api/apps/:appId/users", usersRoutes);
|
|
251569
251479
|
const functionManager = new FunctionManager(functions, devLogger, options8.denoWrapperPath);
|
|
251570
251480
|
const functionRoutes = createFunctionRouter(functionManager, devLogger);
|
|
251571
251481
|
app.use("/api/apps/:appId/functions", functionRoutes);
|
|
@@ -251578,7 +251488,7 @@ async function createDevServer(options8) {
|
|
|
251578
251488
|
R2.info(`Loaded entities: ${db2.getCollectionNames().join(", ")}`);
|
|
251579
251489
|
}
|
|
251580
251490
|
let emitEntityEvent = () => {};
|
|
251581
|
-
const entityRoutes =
|
|
251491
|
+
const entityRoutes = createEntityRoutes(db2, devLogger, remoteProxy, (...args) => emitEntityEvent(...args));
|
|
251582
251492
|
app.use("/api/apps/:appId/entities", entityRoutes);
|
|
251583
251493
|
const { path: mediaFilesDir } = await $dir();
|
|
251584
251494
|
app.use("/media/private/:fileUri", (req, res, next) => {
|
|
@@ -251599,7 +251509,7 @@ async function createDevServer(options8) {
|
|
|
251599
251509
|
}
|
|
251600
251510
|
next();
|
|
251601
251511
|
});
|
|
251602
|
-
app.use("/media",
|
|
251512
|
+
app.use("/media", import_express4.default.static(mediaFilesDir));
|
|
251603
251513
|
const integrationRoutes = createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, devLogger);
|
|
251604
251514
|
app.use("/api/apps/:appId/integration-endpoints", integrationRoutes);
|
|
251605
251515
|
const customIntegrationRoutes = createCustomIntegrationRoutes(remoteProxy, devLogger);
|
|
@@ -256050,4 +255960,4 @@ export {
|
|
|
256050
255960
|
CLIExitError
|
|
256051
255961
|
};
|
|
256052
255962
|
|
|
256053
|
-
//# debugId=
|
|
255963
|
+
//# debugId=8DF79D46442B07AB64756E2164756E21
|