@base44-preview/cli 0.1.32-pr.664.f359bf9 → 0.1.32-pr.665.1a74073

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
@@ -228838,7 +228838,7 @@ function normalizeBase44Env() {
228838
228838
  loadProjectEnvFiles();
228839
228839
 
228840
228840
  // src/cli/index.ts
228841
- import { dirname as dirname29, join as join40 } from "node:path";
228841
+ import { dirname as dirname30, join as join40 } from "node:path";
228842
228842
  import { fileURLToPath as fileURLToPath7 } from "node:url";
228843
228843
 
228844
228844
  // ../../node_modules/@clack/core/dist/index.mjs
@@ -246963,7 +246963,8 @@ async function resolveBuildTarget(projectRoot, overrides = {}) {
246963
246963
  outputDir: resolve6(root, overrides.outputDir ?? site.outputDirectory ?? DEFAULT_SITE.outputDirectory),
246964
246964
  entitiesDir: project?.entitiesDir ?? "entities",
246965
246965
  agentsDir: project?.agentsDir ?? "agents",
246966
- functionsDir: project?.functionsDir ?? "functions"
246966
+ functionsDir: project?.functionsDir ?? "functions",
246967
+ actorsDir: project?.actorsDir ?? "actors"
246967
246968
  };
246968
246969
  }
246969
246970
  async function readSettingsIfPresent(projectRoot) {
@@ -250792,6 +250793,25 @@ function declaredBundle({
250792
250793
  }
250793
250794
  };
250794
250795
  }
250796
+ function declaredActor({
250797
+ name,
250798
+ entry,
250799
+ source,
250800
+ size,
250801
+ digest,
250802
+ staticEgress
250803
+ }) {
250804
+ return {
250805
+ name,
250806
+ entry,
250807
+ source,
250808
+ module: { size, digest },
250809
+ static_egress: staticEgress
250810
+ };
250811
+ }
250812
+ function actorUploadPath(actor) {
250813
+ return `actors/${actor.name}.mjs`;
250814
+ }
250795
250815
  function declaredServingConfig(config) {
250796
250816
  const stated = {
250797
250817
  html_handling: config?.htmlHandling ?? null,
@@ -250846,6 +250866,7 @@ async function createVersion(artifacts, options = {}) {
250846
250866
  }
250847
250867
  } : {},
250848
250868
  backend_bundles: artifacts.backendBundles.map(declaredBundle),
250869
+ actors: artifacts.actors.map(declaredActor),
250849
250870
  entities: artifacts.entities,
250850
250871
  agents: artifacts.agents,
250851
250872
  source_commit: options.sourceCommit
@@ -250854,7 +250875,8 @@ async function createVersion(artifacts, options = {}) {
250854
250875
  ...artifacts.assets,
250855
250876
  ...artifacts.siteWorker?.modules ?? []
250856
250877
  ];
250857
- const slotCount = declaredFiles.length + artifacts.backendBundles.length;
250878
+ const actorsAt = declaredFiles.length + artifacts.backendBundles.length;
250879
+ const slotCount = actorsAt + artifacts.actors.length;
250858
250880
  options.progress?.onDeclared?.({ fileCount: slotCount });
250859
250881
  if (declared.uploads.length !== slotCount) {
250860
250882
  throw new InternalError(`Declared ${slotCount} files but the server signed ${declared.uploads.length} upload URLs.`);
@@ -250863,12 +250885,18 @@ async function createVersion(artifacts, options = {}) {
250863
250885
  if (drifted !== -1) {
250864
250886
  throw new InternalError(`Upload ${drifted} is signed for ${declared.uploads[drifted].path}, but that slot declared ${declaredFiles[drifted].path}.`);
250865
250887
  }
250888
+ const actorDrifted = artifacts.actors.findIndex((actor, index) => declared.uploads[actorsAt + index].path !== actorUploadPath(actor));
250889
+ if (actorDrifted !== -1) {
250890
+ throw new InternalError(`Upload ${actorsAt + actorDrifted} is signed for ${declared.uploads[actorsAt + actorDrifted].path}, but that slot declared the actor ${artifacts.actors[actorDrifted].name}.`);
250891
+ }
250866
250892
  let uploadedFiles = 0;
250867
250893
  await pMap(declared.uploads, async (upload, index) => {
250868
250894
  if (index < declaredFiles.length) {
250869
250895
  await putPresigned(upload, declaredFiles[index].absolutePath);
250870
- } else {
250896
+ } else if (index < actorsAt) {
250871
250897
  await putPresignedBody(upload, artifacts.backendBundles[index - declaredFiles.length].module);
250898
+ } else {
250899
+ await putPresignedBody(upload, artifacts.actors[index - actorsAt].module);
250872
250900
  }
250873
250901
  uploadedFiles++;
250874
250902
  options.progress?.onUpload?.({
@@ -250886,11 +250914,10 @@ async function setEnvironmentVersion(environment, versionId, options = {}) {
250886
250914
  }
250887
250915
  // src/core/version/artifacts.ts
250888
250916
  import { createHash as createHash3 } from "node:crypto";
250889
- import { join as join29, resolve as resolve13 } from "node:path";
250917
+ import { join as join29, resolve as resolve14 } from "node:path";
250890
250918
 
250891
- // src/core/version/functions.ts
250892
- import { createHash as createHash2 } from "node:crypto";
250893
- import { relative as relative6 } from "node:path";
250919
+ // src/core/version/actors.ts
250920
+ import { dirname as dirname22, relative as relative7, resolve as resolve13 } from "node:path";
250894
250921
 
250895
250922
  // ../functions-compiler/src/assembly.ts
250896
250923
  import path17 from "node:path";
@@ -256424,6 +256451,18 @@ function consolePatch(runtimeSecrets) {
256424
256451
  return runtimeSecrets ? `${CONSOLE_PATCH}
256425
256452
  ${RUNTIME_SECRETS_RESERVED_PATCH}` : CONSOLE_PATCH;
256426
256453
  }
256454
+ async function prepareFunction(entry, files, postResponseTelemetry = false, runtimeSecrets = false) {
256455
+ assertNoReservedFilenames(files);
256456
+ return {
256457
+ entry: ENTRY_FILENAME,
256458
+ files: {
256459
+ ...userFiles(files),
256460
+ ...workerRuntimeFiles(),
256461
+ ...runtimeSecrets ? { [ACTIVATION_FILENAME]: activationShimSource() } : {},
256462
+ [ENTRY_FILENAME]: buildEntrySource(entry, postResponseTelemetry, runtimeSecrets)
256463
+ }
256464
+ };
256465
+ }
256427
256466
  var BANNER_FORMAT = 1;
256428
256467
  function buildBanner(entries, telemetry, runtimeSecrets) {
256429
256468
  return `//!b44:${BANNER_FORMAT} ${JSON.stringify({
@@ -256467,6 +256506,50 @@ function activationImport(runtimeSecrets) {
256467
256506
  return runtimeSecrets ? `
256468
256507
  import { ensureActivation, takeActivationChallenge, withoutActivationHeaders } from "./${ACTIVATION_FILENAME}";` : "";
256469
256508
  }
256509
+ function buildEntrySource(userEntry, telemetry, runtimeSecrets = false) {
256510
+ const userImport = `./${userEntry.replace(/^\.\//, "")}`;
256511
+ const handlerExpr = telemetry ? "_b44AttachTelemetry(await handler(request, info))" : runtimeSecrets ? "await handler(request, info)" : "handler(request, info)";
256512
+ const guard = activationGuard(runtimeSecrets);
256513
+ const returnExpr = guard(handlerExpr);
256514
+ return `// Auto-generated by the base44 bundler. Do not edit.
256515
+
256516
+ import { currentWorkerRuntimeContext as _b44Context, runWithWorkerEnvironment as _b44Run } from ${JSON.stringify(RUNTIME_CONTEXT_SPECIFIER)};
256517
+ import { getRegisteredHandler, installStaticEgressFetch } from "./${SHIM_FILENAME}";${activationImport(runtimeSecrets)}
256518
+
256519
+ ${consolePatch(runtimeSecrets)}
256520
+ // Static egress reads workerEnv from the active request store. Install it
256521
+ // before telemetry so telemetry remains the outermost fetch wrapper.
256522
+ installStaticEgressFetch();
256523
+ ${telemetry ? TELEMETRY_PATCH : ""}
256524
+
256525
+ let _b44Init = null;
256526
+ export default {
256527
+ async fetch(request, env, ctx) {
256528
+ ${runtimeSecrets ? ACTIVATION_TAKE : ""} const _b44Env = (request.headers.get('base44-functions-version') ?? '') === 'prod' ? 'prod' : 'preview';
256529
+ return _b44Run({ env: _b44Env, secrets: ${runtimeSecrets ? "process.env" : "env"}, workerEnv: env, waitUntil: (p) => ctx.waitUntil(p)${telemetry ? `, ${TELEMETRY_STORE_FIELDS}` : ""} }, async () => {
256530
+ ${runtimeSecrets ? ACTIVATION_GATE : ""} if (!_b44Init) _b44Init = import(${JSON.stringify(userImport)}).catch(e => { _b44Init = null; throw e; });
256531
+ const _b44Mod = await _b44Init;
256532
+ // Deno.serve capture wins (legacy contract, zero behavior change);
256533
+ // a default-exported handler is the new-contract fallback.
256534
+ const handler = getRegisteredHandler() ?? (typeof _b44Mod?.default === 'function' ? _b44Mod.default : null);
256535
+ if (!handler) {
256536
+ return ${guard(`new Response(
256537
+ "The function must export default a request handler or call Deno.serve()",
256538
+ { status: 503 },
256539
+ )`)};
256540
+ }
256541
+ // Deno's handler signature is (request, info). Cloudflare doesn't expose a
256542
+ // connection address the same way; pass a best-effort placeholder. Real
256543
+ // client IP is available via the "cf-connecting-ip" request header.
256544
+ const info = {
256545
+ remoteAddr: { transport: "tcp", hostname: "0.0.0.0", port: 0 },
256546
+ };
256547
+ return ${returnExpr};
256548
+ });
256549
+ },
256550
+ };
256551
+ `;
256552
+ }
256470
256553
  function buildFunctionModuleSource(functionName, userEntry) {
256471
256554
  const userImport = `./${userEntry.replace(/^\.\//, "")}`;
256472
256555
  return `// Auto-generated by the base44 bundler. Do not edit.
@@ -256769,6 +256852,284 @@ function runtimeContextVirtualPlugin() {
256769
256852
  };
256770
256853
  }
256771
256854
 
256855
+ // ../functions-compiler/src/actor-compat.ts
256856
+ var ACTOR_ENTRY_FILENAME2 = "__base44_actor_entry.mjs";
256857
+ var ACTOR_PRELUDE_FILENAME = "__base44_actor_prelude.mjs";
256858
+ var ACTOR_AUTH_FILENAME = "__base44_actor_auth.mjs";
256859
+ var ACTORS_PREFIX = "base44/actors/";
256860
+ var ENTRY_SUFFIX = "/entry.ts";
256861
+ function actorNameFromEntry(entry) {
256862
+ if (!entry.startsWith(ACTORS_PREFIX) || !entry.endsWith(ENTRY_SUFFIX))
256863
+ return null;
256864
+ const name = entry.slice(ACTORS_PREFIX.length, -ENTRY_SUFFIX.length);
256865
+ return name && !name.includes("/") ? name : null;
256866
+ }
256867
+ function applyActorCompat(entry, files) {
256868
+ const actorName = actorNameFromEntry(entry);
256869
+ if (!actorName || files[entry] === undefined)
256870
+ return null;
256871
+ assertNoReservedFilenames(files);
256872
+ if (ACTOR_PRELUDE_FILENAME in files) {
256873
+ throw new Error(`Reserved filename "${ACTOR_PRELUDE_FILENAME}" in actor bundle — ` + "it is generated by the bundler. Rename the file.");
256874
+ }
256875
+ if (ACTOR_AUTH_FILENAME in files) {
256876
+ throw new Error(`Reserved filename "${ACTOR_AUTH_FILENAME}" in actor bundle — ` + "it is generated by the bundler. Rename the file.");
256877
+ }
256878
+ const handlerName = actorName;
256879
+ const doClassName = handlerName;
256880
+ const prelude = buildPrelude();
256881
+ const entryWrapper = buildEntryWrapper(doClassName, entry);
256882
+ return {
256883
+ entry: ACTOR_ENTRY_FILENAME2,
256884
+ files: {
256885
+ ...files,
256886
+ ...workerRuntimeFiles(),
256887
+ [ACTOR_AUTH_FILENAME]: buildActorAuth(),
256888
+ [ACTOR_PRELUDE_FILENAME]: prelude,
256889
+ [ACTOR_ENTRY_FILENAME2]: entryWrapper
256890
+ },
256891
+ handlerName,
256892
+ doClassName
256893
+ };
256894
+ }
256895
+ function buildActorAuth() {
256896
+ return `// Auto-generated by the base44 bundler. Do not edit.
256897
+ const TOKEN_HEADER = "X-Base44-Actor-Token";
256898
+ const IDENTITY_HEADER = "X-Base44-Actor-Identity";
256899
+ const CLOCK_SKEW_SECONDS = 30;
256900
+ const TOKEN_TTL_SECONDS = 300;
256901
+
256902
+ const decodeSegment = (segment) => {
256903
+ const normalized = segment.replace(/-/g, "+").replace(/_/g, "/");
256904
+ const padded = normalized + "=".repeat((4 - normalized.length % 4) % 4);
256905
+ const binary = atob(padded);
256906
+ return new Uint8Array([...binary].map((character) => character.charCodeAt(0)));
256907
+ };
256908
+
256909
+ const decodeJsonSegment = (segment) =>
256910
+ JSON.parse(new TextDecoder().decode(decodeSegment(segment)));
256911
+
256912
+ const unauthorized = () => ({
256913
+ ok: false,
256914
+ response: new Response("Unauthorized", { status: 401 }),
256915
+ });
256916
+
256917
+ const validPrincipal = (principal) => {
256918
+ if (principal === null || typeof principal !== "object" || Array.isArray(principal)) return false;
256919
+ if (principal.type === "authenticated") {
256920
+ return typeof principal.userId === "string" && principal.userId.length > 0 && principal.userId.length <= 128;
256921
+ }
256922
+ if (principal.type === "anonymous") {
256923
+ return typeof principal.anonymousId === "string" && principal.anonymousId.length > 0 && principal.anonymousId.length <= 128;
256924
+ }
256925
+ return false;
256926
+ };
256927
+
256928
+ export async function verifyActorConnection(request, env, actorName, room) {
256929
+ const publicKey = env.BASE44_ACTOR_PUBLIC_KEY;
256930
+ const scriptId = env.BASE44_ACTOR_SCRIPT_ID;
256931
+ const token = request.headers.get(TOKEN_HEADER) ?? new URL(request.url).searchParams.get("token");
256932
+ if (
256933
+ typeof publicKey !== "string" || !publicKey ||
256934
+ typeof scriptId !== "string" || !scriptId ||
256935
+ typeof token !== "string" || token.length > 4096
256936
+ ) return unauthorized();
256937
+
256938
+ const parts = token.split(".");
256939
+ if (parts.length !== 3) return unauthorized();
256940
+ try {
256941
+ const header = decodeJsonSegment(parts[0]);
256942
+ const claims = decodeJsonSegment(parts[1]);
256943
+ if (header?.alg !== "EdDSA" || (header.typ !== undefined && header.typ !== "JWT")) {
256944
+ return unauthorized();
256945
+ }
256946
+ const key = await crypto.subtle.importKey(
256947
+ "raw",
256948
+ decodeSegment(publicKey),
256949
+ { name: "Ed25519" },
256950
+ false,
256951
+ ["verify"],
256952
+ );
256953
+ const validSignature = await crypto.subtle.verify(
256954
+ { name: "Ed25519" },
256955
+ key,
256956
+ decodeSegment(parts[2]),
256957
+ new TextEncoder().encode(parts[0] + "." + parts[1]),
256958
+ );
256959
+ if (!validSignature) return unauthorized();
256960
+
256961
+ const now = Math.floor(Date.now() / 1000);
256962
+ const times = [claims.iat, claims.nbf, claims.exp];
256963
+ if (!times.every(Number.isInteger)) return unauthorized();
256964
+ if (
256965
+ claims.iss !== "base44" ||
256966
+ claims.aud !== "base44-actor-connect" ||
256967
+ claims.purpose !== "actor-connect" ||
256968
+ claims.v !== 1 ||
256969
+ typeof claims.jti !== "string" || !claims.jti || claims.jti.length > 64 ||
256970
+ claims.iat > now + CLOCK_SKEW_SECONDS ||
256971
+ claims.nbf > now + CLOCK_SKEW_SECONDS ||
256972
+ claims.exp < now - CLOCK_SKEW_SECONDS ||
256973
+ claims.exp <= claims.iat || claims.exp - claims.iat > TOKEN_TTL_SECONDS ||
256974
+ claims.app_id !== env.BASE44_APP_ID ||
256975
+ claims.actor_name !== actorName ||
256976
+ claims.actor_script_id !== scriptId ||
256977
+ claims.room !== room ||
256978
+ claims.connection_id !== new URL(request.url).searchParams.get("_pk") ||
256979
+ claims.runtime_mode !== (env.BASE44_FUNCTIONS_VERSION === "prod" ? "prod" : "preview") ||
256980
+ !validPrincipal(claims.principal)
256981
+ ) return unauthorized();
256982
+
256983
+ return {
256984
+ ok: true,
256985
+ identity: Object.freeze({ ...claims.principal }),
256986
+ runtimeMode: claims.runtime_mode,
256987
+ };
256988
+ } catch {
256989
+ return unauthorized();
256990
+ }
256991
+ }
256992
+
256993
+ export function authorizedActorRequest(request, identity, actorName, room, runtimeMode) {
256994
+ const url = new URL(request.url);
256995
+ url.searchParams.delete("token");
256996
+ url.pathname = "/parties/" + encodeURIComponent(actorName) + "/" + encodeURIComponent(room);
256997
+ const headers = new Headers(request.headers);
256998
+ headers.delete(TOKEN_HEADER);
256999
+ headers.set(IDENTITY_HEADER, JSON.stringify(identity));
257000
+ headers.set("base44-functions-version", runtimeMode === "prod" ? "prod" : "preview");
257001
+ return new Request(new Request(url.toString(), request), { headers });
257002
+ }
257003
+ `;
257004
+ }
257005
+ function buildPrelude() {
257006
+ return `// Auto-generated by the base44 bundler. Do not edit.
257007
+ import { currentWorkerRuntimeContext as _b44Context } from ${JSON.stringify(RUNTIME_CONTEXT_SPECIFIER)};
257008
+ import { installStaticEgressFetch } from "./${SHIM_FILENAME}";
257009
+
257010
+ ${CONSOLE_PATCH}
257011
+ installStaticEgressFetch();
257012
+ `;
257013
+ }
257014
+ function buildEntryWrapper(doClassName, userEntry) {
257015
+ const userImport = `./${userEntry.replace(/^\.\//, "")}`;
257016
+ return `// Auto-generated by the base44 bundler. Do not edit.
257017
+ // The prelude is intentionally the first dependency: it installs the fetch
257018
+ // shim before the user module evaluates while this static default import keeps
257019
+ // missing-default actors as bundle-time errors.
257020
+ import "./${ACTOR_PRELUDE_FILENAME}";
257021
+ import Base44UserActor from ${JSON.stringify(userImport)};
257022
+ import { runWithWorkerEnvironment as _b44Run } from ${JSON.stringify(RUNTIME_CONTEXT_SPECIFIER)};
257023
+ import { authorizedActorRequest as _b44AuthorizedActorRequest, verifyActorConnection as _b44VerifyActorConnection } from "./${ACTOR_AUTH_FILENAME}";
257024
+
257025
+ const _b44ActorState = new WeakMap();
257026
+ const _b44RunWithActorEnvironment = (ctx, env, runtimeEnv, callback) => _b44Run({
257027
+ env: runtimeEnv,
257028
+ secrets: env,
257029
+ workerEnv: env,
257030
+ waitUntil: (promise) => ctx.waitUntil(promise),
257031
+ }, callback);
257032
+ const _b44ConstructActor = (ctx, env, newTarget) => _b44RunWithActorEnvironment(
257033
+ ctx,
257034
+ env,
257035
+ "prod",
257036
+ () => {
257037
+ // A derived constructor may return an explicitly constructed instance.
257038
+ // This keeps the user's constructor and class-field initializers inside the
257039
+ // request-scoped Worker environment without changing the exported subclass.
257040
+ const actor = Reflect.construct(Base44UserActor, [ctx, env], newTarget);
257041
+ _b44ActorState.set(actor, { ctx, env, runtimeEnv: null });
257042
+ return actor;
257043
+ },
257044
+ );
257045
+ const _b44RunActor = (actor, request, callback) => {
257046
+ const state = _b44ActorState.get(actor);
257047
+ const runtimeEnv = request
257048
+ ? ((request.headers.get("base44-functions-version") ?? "") === "prod" ? "prod" : "preview")
257049
+ : (state.runtimeEnv ?? "prod");
257050
+ state.runtimeEnv = runtimeEnv;
257051
+ return _b44RunWithActorEnvironment(state.ctx, state.env, runtimeEnv, callback);
257052
+ };
257053
+
257054
+ export class ${doClassName} extends Base44UserActor {
257055
+ // Read by the shim's service-token exchange: the assertion's actor_name claim
257056
+ // selects the verification key on the platform side. A static (not .name) so
257057
+ // minification can't change it.
257058
+ static _b44ActorName = ${JSON.stringify(doClassName)};
257059
+
257060
+ constructor(ctx, env) {
257061
+ return _b44ConstructActor(ctx, env, new.target);
257062
+ }
257063
+
257064
+ fetch(request) {
257065
+ return _b44RunActor(this, request, () => super.fetch(request));
257066
+ }
257067
+
257068
+ onConnect(...args) {
257069
+ return _b44RunActor(this, null, () => super.onConnect(...args));
257070
+ }
257071
+
257072
+ onMessage(...args) {
257073
+ return _b44RunActor(this, null, () => super.onMessage(...args));
257074
+ }
257075
+
257076
+ onClose(...args) {
257077
+ return _b44RunActor(this, null, () => super.onClose(...args));
257078
+ }
257079
+
257080
+ onAlarm(...args) {
257081
+ return _b44RunActor(this, null, () => super.onAlarm(...args));
257082
+ }
257083
+
257084
+ onStart(...args) {
257085
+ return _b44RunActor(this, null, () => super.onStart(...args));
257086
+ }
257087
+
257088
+ onError(...args) {
257089
+ return _b44RunActor(this, null, () => super.onError(...args));
257090
+ }
257091
+ }
257092
+ export default {
257093
+ async fetch(request, env, ctx) {
257094
+ const url = new URL(request.url);
257095
+ const parts = url.pathname.split("/");
257096
+ const direct = parts[1] === "rooms" && parts.length === 3;
257097
+ const legacy = parts[1] === "parties" && parts.length === 4;
257098
+ if (direct || legacy) {
257099
+ // Decode the room: the token was verified against the decoded instance id,
257100
+ // so an escaped room must map to the same Durable Object.
257101
+ const namespace = direct ? "${doClassName}" : parts[2];
257102
+ const encodedRoom = direct ? parts[2] : parts[3];
257103
+ let room;
257104
+ try { room = decodeURIComponent(encodedRoom); } catch { return new Response("Invalid room", { status: 400 }); }
257105
+ let actorRequest = request;
257106
+ if (direct || typeof env.BASE44_ACTOR_PUBLIC_KEY === "string") {
257107
+ const verification = await _b44VerifyActorConnection(request, env, "${doClassName}", room);
257108
+ if (!verification.ok) return verification.response;
257109
+ actorRequest = _b44AuthorizedActorRequest(
257110
+ request,
257111
+ verification.identity,
257112
+ "${doClassName}",
257113
+ room,
257114
+ verification.runtimeMode,
257115
+ );
257116
+ }
257117
+ const doNs = env["${doClassName}"];
257118
+ if (doNs && typeof doNs.idFromName === "function") {
257119
+ const stub = doNs.get(doNs.idFromName(room));
257120
+ const req = new Request(actorRequest);
257121
+ req.headers.set("x-partykit-room", room);
257122
+ req.headers.set("x-partykit-namespace", namespace);
257123
+ return stub.fetch(req);
257124
+ }
257125
+ return new Response("DO binding not found", { status: 503 });
257126
+ }
257127
+ return new Response("Not found", { status: 404 });
257128
+ },
257129
+ };
257130
+ `;
257131
+ }
257132
+
256772
257133
  // ../../node_modules/zod/v3/helpers/util.js
256773
257134
  var util;
256774
257135
  (function(util) {
@@ -261273,6 +261634,51 @@ function setSpanTags(tags) {
261273
261634
  // ../functions-compiler/src/bundler.ts
261274
261635
  var NORMALIZED_MAIN_MODULE = "_bundled.mjs";
261275
261636
  var MAX_PARALLEL_COMPILES = 4;
261637
+ async function bundle(req) {
261638
+ let actor;
261639
+ try {
261640
+ actor = applyActorCompat(req.entry, req.files);
261641
+ } catch (e) {
261642
+ return denoCompatErrorOrThrow(e);
261643
+ }
261644
+ if (actor) {
261645
+ if (req.runtimeSecrets) {
261646
+ return denoCompatErrorOrThrow(new DenoCompatError("runtimeSecrets is not supported for Actor entries: an Actor reads secrets " + "from its Durable Object env, so it must be deployed in binding mode."));
261647
+ }
261648
+ const outcome = await installAndCompile({
261649
+ entry: actor.entry,
261650
+ files: actor.files
261651
+ });
261652
+ if (outcome.ok) {
261653
+ return {
261654
+ ok: true,
261655
+ module: outcome.module,
261656
+ main_module: NORMALIZED_MAIN_MODULE,
261657
+ warnings: outcome.warnings,
261658
+ handler_name: actor.handlerName,
261659
+ do_class_name: actor.doClassName
261660
+ };
261661
+ }
261662
+ return { ok: false, stage: outcome.stage, errors: outcome.errors };
261663
+ }
261664
+ let prepared;
261665
+ try {
261666
+ prepared = await prepareFunction(req.entry, req.files, req.postResponseTelemetry, req.runtimeSecrets);
261667
+ } catch (e) {
261668
+ return denoCompatErrorOrThrow(e);
261669
+ }
261670
+ const outcome = await installAndCompile(prepared);
261671
+ if (outcome.ok) {
261672
+ return {
261673
+ ok: true,
261674
+ module: outcome.module,
261675
+ main_module: NORMALIZED_MAIN_MODULE,
261676
+ warnings: outcome.warnings,
261677
+ ...activationField(req.runtimeSecrets ?? false)
261678
+ };
261679
+ }
261680
+ return { ok: false, stage: outcome.stage, errors: outcome.errors };
261681
+ }
261276
261682
  function activationField(runtimeSecrets) {
261277
261683
  return runtimeSecrets ? { activation: ACTIVATION_MODE } : {};
261278
261684
  }
@@ -261460,6 +261866,16 @@ async function installAndCompile(prepared) {
261460
261866
  return { ok: false, stage: "esbuild", errors: result.errors };
261461
261867
  });
261462
261868
  }
261869
+ function denoCompatErrorOrThrow(e) {
261870
+ if (e instanceof DenoCompatError) {
261871
+ return {
261872
+ ok: false,
261873
+ stage: "deno_compat",
261874
+ errors: [denoCompatErrorItem(e)]
261875
+ };
261876
+ }
261877
+ throw e;
261878
+ }
261463
261879
  function denoCompatErrorItem(e) {
261464
261880
  return { message: e.message, file: e.file };
261465
261881
  }
@@ -261662,6 +262078,8 @@ async function mapWithConcurrency2(items, limit, fn) {
261662
262078
  return results;
261663
262079
  }
261664
262080
  // src/core/version/functions.ts
262081
+ import { createHash as createHash2 } from "node:crypto";
262082
+ import { relative as relative6 } from "node:path";
261665
262083
  var SHARD_POLICY = {
261666
262084
  shardSize: 100,
261667
262085
  globalShardSize: 100,
@@ -261669,11 +262087,11 @@ var SHARD_POLICY = {
261669
262087
  gzipCapBytes: 9500000
261670
262088
  };
261671
262089
  var COMPILE_MODES = { runtimeSecrets: false, postResponseTelemetry: false };
261672
- async function requireCompilerRuntime() {
262090
+ async function requireCompilerRuntime(what = "Backend functions") {
261673
262091
  try {
261674
262092
  await Promise.all([import("esbuild"), import("@deno/loader")]);
261675
262093
  } catch (error) {
261676
- throw new DependencyNotFoundError("Backend functions cannot be compiled by this installation of the CLI.", {
262094
+ throw new DependencyNotFoundError(`${what} cannot be compiled by this installation of the CLI.`, {
261677
262095
  hints: [{ message: "Install the CLI from npm: npm install -g base44" }],
261678
262096
  cause: error instanceof Error ? error : undefined
261679
262097
  });
@@ -261730,6 +262148,97 @@ async function compileBackendBundles(root, functionsDir) {
261730
262148
  });
261731
262149
  }
261732
262150
 
262151
+ // src/core/version/actors.ts
262152
+ var MAX_ACTORS = 50;
262153
+ var COMPILE_CONCURRENCY = 4;
262154
+ var ACTORS_ROOT = "base44/actors";
262155
+ var SHARED_ROOT = "base44/shared";
262156
+ function forwardSlashed(from, to) {
262157
+ return relative7(from, to).split(/[/\\]/).join("/");
262158
+ }
262159
+ async function readSharedFiles2(actorsDir) {
262160
+ const sharedDir = resolve13(actorsDir, "..", "shared");
262161
+ if (!await pathExists(sharedDir)) {
262162
+ return {};
262163
+ }
262164
+ const paths = await globby(BACKEND_FILE_GLOB, {
262165
+ cwd: sharedDir,
262166
+ absolute: true
262167
+ });
262168
+ const files = {};
262169
+ for (const path of paths.sort()) {
262170
+ files[`${SHARED_ROOT}/${forwardSlashed(sharedDir, path)}`] = await readTextFile(path);
262171
+ }
262172
+ return files;
262173
+ }
262174
+ async function compilerInput2(actor, shared) {
262175
+ const actorDir = dirname22(actor.entryPath);
262176
+ const entry = `${ACTORS_ROOT}/${actor.name}/entry.ts`;
262177
+ const source = await readTextFile(actor.entryPath);
262178
+ const candidates = { ...shared };
262179
+ for (const filePath of actor.filePaths) {
262180
+ if (filePath !== actor.entryPath) {
262181
+ candidates[`${ACTORS_ROOT}/${actor.name}/${forwardSlashed(actorDir, filePath)}`] = await readTextFile(filePath);
262182
+ }
262183
+ }
262184
+ candidates[entry] = source;
262185
+ return {
262186
+ entry,
262187
+ files: await collectReachableFiles(entry, candidates),
262188
+ source
262189
+ };
262190
+ }
262191
+ async function compileActors(actorsDir) {
262192
+ const actors = await readAllActors(actorsDir);
262193
+ if (actors.length === 0) {
262194
+ return [];
262195
+ }
262196
+ if (actors.length > MAX_ACTORS) {
262197
+ throw new InvalidInputError(`Too many actors: found ${actors.length}, the limit is ${MAX_ACTORS}.`);
262198
+ }
262199
+ await requireCompilerRuntime("Actors");
262200
+ const shared = await readSharedFiles2(actorsDir);
262201
+ const sorted = [...actors].sort((a, b) => a.name < b.name ? -1 : 1);
262202
+ const compiled = await pMap(sorted, async (actor) => {
262203
+ const input = await compilerInput2(actor, shared);
262204
+ const result = await bundle({ entry: input.entry, files: input.files });
262205
+ return {
262206
+ name: actor.name,
262207
+ entry: input.entry,
262208
+ source: input.source,
262209
+ result
262210
+ };
262211
+ }, { concurrency: COMPILE_CONCURRENCY });
262212
+ const failures = compiled.flatMap(({ name, result }) => result.ok ? [] : [
262213
+ {
262214
+ function: name,
262215
+ message: `Actor "${name}" failed to compile.`,
262216
+ errors: result.errors
262217
+ }
262218
+ ]);
262219
+ if (failures.length > 0) {
262220
+ throw new InvalidInputError(`Actors failed to compile (${failures.length} error${failures.length === 1 ? "" : "s"}).`, { details: failures.map(describeFailure) });
262221
+ }
262222
+ return compiled.map(({ name, entry, source, result }) => {
262223
+ const module = new TextEncoder().encode(compiledModule(name, result));
262224
+ return {
262225
+ name,
262226
+ entry,
262227
+ source,
262228
+ module,
262229
+ size: module.byteLength,
262230
+ digest: sha256(module),
262231
+ staticEgress: STATIC_EGRESS_ARTIFACT_MARKER
262232
+ };
262233
+ });
262234
+ }
262235
+ function compiledModule(name, result) {
262236
+ if (!result.ok || result.do_class_name !== name) {
262237
+ throw new InternalError(`Actor "${name}" did not compile as an actor of that name.`);
262238
+ }
262239
+ return result.module;
262240
+ }
262241
+
261733
262242
  // src/core/version/publish.ts
261734
262243
  import { randomUUID as randomUUID4 } from "node:crypto";
261735
262244
  var DEFAULT_ENVIRONMENT = "production";
@@ -261782,7 +262291,7 @@ async function collectBuildOutput(outputDir, options = {}) {
261782
262291
  }
261783
262292
  async function describeSiteWorker(built) {
261784
262293
  const { config, modules } = built;
261785
- const entry = resolve13(config.configDir, config.main);
262294
+ const entry = resolve14(config.configDir, config.main);
261786
262295
  const main = modules.find((m) => m.absolutePath === entry)?.name;
261787
262296
  if (!main) {
261788
262297
  throw new InvalidInputError(`The Worker's entry module ${config.main} is not among the ${modules.length} modules collected from ${config.configDir}.`);
@@ -261833,6 +262342,7 @@ async function collectArtifacts(target) {
261833
262342
  }),
261834
262343
  ...siteWorker ? { siteWorker } : {},
261835
262344
  backendBundles: await tagStep2("build", () => compileBackendBundles(target.root, join29(target.configDir, target.functionsDir))),
262345
+ actors: await tagStep2("build", () => compileActors(join29(target.configDir, target.actorsDir))),
261836
262346
  ...await collectResources(target.configDir, target)
261837
262347
  };
261838
262348
  }
@@ -262290,7 +262800,7 @@ function getSecretsListCommand() {
262290
262800
  }
262291
262801
 
262292
262802
  // src/cli/commands/secrets/set.ts
262293
- import { resolve as resolve14 } from "node:path";
262803
+ import { resolve as resolve15 } from "node:path";
262294
262804
  function parseEntries(entries) {
262295
262805
  const secrets = {};
262296
262806
  for (const entry of entries) {
@@ -262321,7 +262831,7 @@ async function setSecretsAction({ log, runTask }, entries, options) {
262321
262831
  validateInput(entries, options);
262322
262832
  let secrets;
262323
262833
  if (options.envFile) {
262324
- secrets = await parseEnvFile(resolve14(options.envFile));
262834
+ secrets = await parseEnvFile(resolve15(options.envFile));
262325
262835
  if (Object.keys(secrets).length === 0) {
262326
262836
  throw new InvalidInputError("The env file contains no valid KEY=VALUE entries.");
262327
262837
  }
@@ -262350,7 +262860,7 @@ function getSecretsCommand() {
262350
262860
  }
262351
262861
 
262352
262862
  // src/cli/commands/site/deploy.ts
262353
- import { resolve as resolve15 } from "node:path";
262863
+ import { resolve as resolve16 } from "node:path";
262354
262864
  async function deployAction2(ctx, options) {
262355
262865
  const { isNonInteractive } = ctx;
262356
262866
  if (isNonInteractive && !options.yes) {
@@ -262419,7 +262929,7 @@ async function deployTarball({ runTask }, project) {
262419
262929
  }
262420
262930
  function siteOutputDir(project) {
262421
262931
  const { outputDirectory = DEFAULT_SITE.outputDirectory } = siteOrDefault(project);
262422
- return resolve15(project.root, outputDirectory);
262932
+ return resolve16(project.root, outputDirectory);
262423
262933
  }
262424
262934
  function getSiteDeployCommand() {
262425
262935
  const command = new Base44Command("deploy").description("Deploy built site files to Base44 hosting").option("-y, --yes", "Skip confirmation prompt").option("--build", "Build the site before deploying (skips the prompt)").option("--no-build", "Deploy without building (skips the prompt)");
@@ -263247,7 +263757,7 @@ function getWorkspaceCommand() {
263247
263757
  // src/cli/dev/dev-server/main.ts
263248
263758
  var import_cors = __toESM(require_lib4(), 1);
263249
263759
  var import_express6 = __toESM(require_express(), 1);
263250
- import { dirname as dirname27, join as join38 } from "node:path";
263760
+ import { dirname as dirname28, join as join38 } from "node:path";
263251
263761
 
263252
263762
  // ../../node_modules/get-port/index.js
263253
263763
  import net from "node:net";
@@ -263377,7 +263887,7 @@ var $tmpName = promisify12(tmp.tmpName);
263377
263887
 
263378
263888
  // src/cli/dev/dev-server/function-manager.ts
263379
263889
  import { spawn as spawn3 } from "node:child_process";
263380
- import { dirname as dirname24, join as join34 } from "node:path";
263890
+ import { dirname as dirname25, join as join34 } from "node:path";
263381
263891
  import { pathToFileURL as pathToFileURL6 } from "node:url";
263382
263892
 
263383
263893
  // src/cli/dev/dev-server/base-function-manager.ts
@@ -263482,7 +263992,7 @@ class FunctionManager extends BaseFunctionManager {
263482
263992
  }
263483
263993
  spawnFunction(func, port) {
263484
263994
  this.logger.log(`Spawning function "${func.name}" on port ${port}`);
263485
- const importMapPath = join34(dirname24(this.wrapperPath), "import-map.json");
263995
+ const importMapPath = join34(dirname25(this.wrapperPath), "import-map.json");
263486
263996
  const process2 = spawn3("deno", ["run", "--allow-all", "--import-map", importMapPath, this.wrapperPath], {
263487
263997
  env: {
263488
263998
  ...globalThis.process.env,
@@ -265211,7 +265721,7 @@ function createCustomIntegrationRoutes(remoteProxy, logger) {
265211
265721
 
265212
265722
  // src/cli/dev/dev-server/watcher.ts
265213
265723
  import { EventEmitter as EventEmitter4 } from "node:events";
265214
- import { relative as relative10 } from "node:path";
265724
+ import { relative as relative11 } from "node:path";
265215
265725
 
265216
265726
  // ../../node_modules/chokidar/index.js
265217
265727
  import { EventEmitter as EventEmitter3 } from "node:events";
@@ -266896,7 +267406,7 @@ class WatchBase44 extends EventEmitter4 {
266896
267406
  ignoreInitial: true
266897
267407
  });
266898
267408
  watcher.on("all", import_debounce.default(async (_event, path) => {
266899
- this.emit("change", name, relative10(targetPath, path));
267409
+ this.emit("change", name, relative11(targetPath, path));
266900
267410
  }, WATCH_DEBOUNCE_MS));
266901
267411
  watcher.on("error", (err) => {
266902
267412
  this.logger.error(`Watch handler failed for ${targetPath}`, err);
@@ -267008,8 +267518,8 @@ async function createDevServer(options) {
267008
267518
  broadcastEntityEvent(io, appId, entityName, event);
267009
267519
  };
267010
267520
  const base44ConfigWatcher = new WatchBase44({
267011
- functions: join38(dirname27(project.configPath), project.functionsDir),
267012
- entities: join38(dirname27(project.configPath), project.entitiesDir)
267521
+ functions: join38(dirname28(project.configPath), project.functionsDir),
267522
+ entities: join38(dirname28(project.configPath), project.entitiesDir)
267013
267523
  }, devLogger);
267014
267524
  base44ConfigWatcher.on("change", async (name) => {
267015
267525
  try {
@@ -267369,7 +267879,7 @@ Examples:
267369
267879
  }
267370
267880
 
267371
267881
  // src/cli/commands/project/eject.ts
267372
- import { resolve as resolve19 } from "node:path";
267882
+ import { resolve as resolve20 } from "node:path";
267373
267883
  var import_kebabCase2 = __toESM(require_kebabCase(), 1);
267374
267884
  async function eject(ctx, options, command) {
267375
267885
  const { log, runTask, isNonInteractive } = ctx;
@@ -267433,7 +267943,7 @@ async function eject(ctx, options, command) {
267433
267943
  Ne("Operation cancelled.");
267434
267944
  throw new CLIExitError(0);
267435
267945
  }
267436
- const resolvedPath = resolve19(selectedPath);
267946
+ const resolvedPath = resolve20(selectedPath);
267437
267947
  await runTask("Downloading your project's code...", async (updateMessage) => {
267438
267948
  await createProjectFilesForExistingProject({
267439
267949
  projectId,
@@ -267538,7 +268048,7 @@ var import_detect_agent = __toESM(require_dist5(), 1);
267538
268048
  import { release, type } from "node:os";
267539
268049
 
267540
268050
  // ../../node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
267541
- import { dirname as dirname28, posix, sep as sep2 } from "path";
268051
+ import { dirname as dirname29, posix, sep as sep2 } from "path";
267542
268052
  function createModulerModifier() {
267543
268053
  const getModuleFromFileName = createGetModuleFromFilename();
267544
268054
  return async (frames) => {
@@ -267547,7 +268057,7 @@ function createModulerModifier() {
267547
268057
  return frames;
267548
268058
  };
267549
268059
  }
267550
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname28(process.argv[1]) : process.cwd(), isWindows = sep2 === "\\") {
268060
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname29(process.argv[1]) : process.cwd(), isWindows = sep2 === "\\") {
267551
268061
  const normalizedBase = isWindows ? normalizeWindowsPath2(basePath) : basePath;
267552
268062
  return (filename) => {
267553
268063
  if (!filename)
@@ -271536,7 +272046,7 @@ function addCommandInfoToErrorReporter(program, errorReporter) {
271536
272046
  });
271537
272047
  }
271538
272048
  // src/cli/index.ts
271539
- var __dirname4 = dirname29(fileURLToPath7(import.meta.url));
272049
+ var __dirname4 = dirname30(fileURLToPath7(import.meta.url));
271540
272050
  async function runCLI(options) {
271541
272051
  ensureNpmAssets(join40(__dirname4, "../assets"));
271542
272052
  const errorReporter = new ErrorReporter;
@@ -271577,4 +272087,4 @@ export {
271577
272087
  runCLI
271578
272088
  };
271579
272089
 
271580
- //# debugId=FAC4CC784F55ED6664756E2164756E21
272090
+ //# debugId=02073B02CE22EAE264756E2164756E21