@base44-preview/cli 0.1.21-pr.642.f600707 → 0.1.22-pr.644.4e391ba

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.
@@ -11,6 +11,11 @@
11
11
  * - BASE44_APP_BASE_URL: App's published URL / subdomain (used for function calls)
12
12
  * - BASE44_PRIVILEGED: When "true", adds the X-Bypass-RLS header (bypass RLS)
13
13
  * - BASE44_DATA_ENV: When set, adds the X-Data-Env header (target data environment)
14
+ * - BASE44_SERVICE_TOKEN: When set, passed as `serviceToken` (enables `base44.asServiceRole`)
15
+ * - BASE44_EXTRA_HEADERS: When set, a JSON object of extra headers on every SDK request
16
+ *
17
+ * BASE44_SERVICE_TOKEN and BASE44_EXTRA_HEADERS are removed from the environment
18
+ * before the user script runs.
14
19
  */
15
20
 
16
21
  export {};
@@ -21,6 +26,10 @@ const accessToken = Deno.env.get("BASE44_ACCESS_TOKEN");
21
26
  const appBaseUrl = Deno.env.get("BASE44_APP_BASE_URL");
22
27
  const isPrivileged = Deno.env.get("BASE44_PRIVILEGED") === "true";
23
28
  const dataEnv = Deno.env.get("BASE44_DATA_ENV");
29
+ const serviceToken = Deno.env.get("BASE44_SERVICE_TOKEN");
30
+ const extraHeaders = Deno.env.get("BASE44_EXTRA_HEADERS");
31
+ Deno.env.delete("BASE44_SERVICE_TOKEN");
32
+ Deno.env.delete("BASE44_EXTRA_HEADERS");
24
33
 
25
34
  if (!scriptPath) {
26
35
  console.error("SCRIPT_PATH environment variable is required");
@@ -39,13 +48,16 @@ if (!appBaseUrl) {
39
48
 
40
49
  import { createClient } from "npm:@base44/sdk";
41
50
 
42
- const customHeaders: Record<string, string> = {};
51
+ const customHeaders: Record<string, string> = extraHeaders
52
+ ? JSON.parse(extraHeaders)
53
+ : {};
43
54
  if (isPrivileged) customHeaders["X-Bypass-RLS"] = "true";
44
55
  if (dataEnv) customHeaders["X-Data-Env"] = dataEnv;
45
56
 
46
57
  const base44 = createClient({
47
58
  appId,
48
59
  token: accessToken,
60
+ ...(serviceToken ? { serviceToken } : {}),
49
61
  serverUrl: appBaseUrl,
50
62
  headers: customHeaders,
51
63
  });
package/dist/cli/index.js CHANGED
@@ -239265,7 +239265,7 @@ import { join as join13 } from "node:path";
239265
239265
  // package.json
239266
239266
  var package_default = {
239267
239267
  name: "base44",
239268
- version: "0.1.21",
239268
+ version: "0.1.22",
239269
239269
  description: "Base44 CLI - Unified interface for managing Base44 applications",
239270
239270
  type: "module",
239271
239271
  bin: {
@@ -247411,7 +247411,8 @@ class Base44Command extends Command2 {
247411
247411
  if (branch !== undefined && !branch.trim()) {
247412
247412
  throw new InvalidInputError("--branch must not be empty.");
247413
247413
  }
247414
- if (this._commandOptions.requireAuth) {
247414
+ const { requireAuth } = this._commandOptions;
247415
+ if (typeof requireAuth === "function" ? requireAuth() : requireAuth) {
247415
247416
  await ensureAuth(this.context);
247416
247417
  }
247417
247418
  if (this._commandOptions.requireAppContext) {
@@ -256163,11 +256164,91 @@ function getDevCommand() {
256163
256164
  return new Base44Command("dev").description("Start the development server").option("-p, --port <number>", "Port for the development server").option("--remote", "Serve the frontend against the production backend instead of a local one").hook("preAction", validateDevOptions).action(devAction);
256164
256165
  }
256165
256166
 
256167
+ // src/core/exec/env-target.ts
256168
+ var ACCESS_TOKEN_VAR = "BASE44_EXEC_ACCESS_TOKEN";
256169
+ var SERVER_URL_VAR = "BASE44_EXEC_SERVER_URL";
256170
+ var SERVICE_TOKEN_VAR = "BASE44_EXEC_SERVICE_TOKEN";
256171
+ var HEADERS_VAR = "BASE44_EXEC_HEADERS";
256172
+ var EXEC_ENV_VARS = [
256173
+ ACCESS_TOKEN_VAR,
256174
+ SERVER_URL_VAR,
256175
+ SERVICE_TOKEN_VAR,
256176
+ HEADERS_VAR
256177
+ ];
256178
+ function read3(env, name) {
256179
+ return env[name]?.trim() || undefined;
256180
+ }
256181
+ function hasExecEnvTarget(env = process.env) {
256182
+ return EXEC_ENV_VARS.some((name) => read3(env, name) !== undefined);
256183
+ }
256184
+ var HeadersSchema = record(string2(), string2());
256185
+ function parseHeaders(raw) {
256186
+ let parsed;
256187
+ try {
256188
+ parsed = JSON.parse(raw);
256189
+ } catch {
256190
+ throw new InvalidInputError(`${HEADERS_VAR} is not valid JSON.`, {
256191
+ hints: [{ message: `Set ${HEADERS_VAR} to e.g. '{"X-Header":"value"}'` }]
256192
+ });
256193
+ }
256194
+ const result = HeadersSchema.safeParse(parsed);
256195
+ if (!result.success) {
256196
+ throw new InvalidInputError(`${HEADERS_VAR} must be a JSON object of string header values.`, {
256197
+ hints: [
256198
+ { message: `Set ${HEADERS_VAR} to e.g. '{"X-Header":"value"}'` }
256199
+ ]
256200
+ });
256201
+ }
256202
+ return result.data;
256203
+ }
256204
+ function readExecEnvTarget(env = process.env) {
256205
+ if (!hasExecEnvTarget(env)) {
256206
+ return;
256207
+ }
256208
+ const token = read3(env, ACCESS_TOKEN_VAR);
256209
+ const serverUrl = read3(env, SERVER_URL_VAR);
256210
+ if (!token || !serverUrl) {
256211
+ const missing = token ? SERVER_URL_VAR : ACCESS_TOKEN_VAR;
256212
+ throw new InvalidInputError(`${missing} is not set. ${ACCESS_TOKEN_VAR} and ${SERVER_URL_VAR} must be set together.`, {
256213
+ hints: [
256214
+ {
256215
+ message: `Set both ${ACCESS_TOKEN_VAR} and ${SERVER_URL_VAR}, or unset all BASE44_EXEC_* variables to use your login`
256216
+ }
256217
+ ]
256218
+ });
256219
+ }
256220
+ if (!URL.canParse(serverUrl)) {
256221
+ throw new InvalidInputError(`${SERVER_URL_VAR} is not a valid URL.`);
256222
+ }
256223
+ const serviceToken = read3(env, SERVICE_TOKEN_VAR);
256224
+ const rawHeaders = read3(env, HEADERS_VAR);
256225
+ return {
256226
+ token,
256227
+ serverUrl,
256228
+ ...serviceToken ? { serviceToken } : {},
256229
+ ...rawHeaders ? { headers: parseHeaders(rawHeaders) } : {}
256230
+ };
256231
+ }
256166
256232
  // src/core/exec/run-script.ts
256167
256233
  import { spawn as spawn4 } from "node:child_process";
256168
256234
  import { copyFileSync, writeFileSync as writeFileSync3 } from "node:fs";
256235
+ var SERVICE_TOKEN_ENV = "BASE44_SERVICE_TOKEN";
256236
+ var EXTRA_HEADERS_ENV = "BASE44_EXTRA_HEADERS";
256237
+ function wrapperOnlyEnv(serviceToken, headers) {
256238
+ return {
256239
+ ...serviceToken ? { [SERVICE_TOKEN_ENV]: serviceToken } : {},
256240
+ ...headers ? { [EXTRA_HEADERS_ENV]: JSON.stringify(headers) } : {}
256241
+ };
256242
+ }
256243
+ function inheritedEnv() {
256244
+ const env = { ...process.env };
256245
+ for (const name of [...EXEC_ENV_VARS, SERVICE_TOKEN_ENV, EXTRA_HEADERS_ENV]) {
256246
+ delete env[name];
256247
+ }
256248
+ return env;
256249
+ }
256169
256250
  async function runScript(options) {
256170
- const { appId, code, local, privileged, dataEnv } = options;
256251
+ const { appId, code, local, privileged, dataEnv, serviceToken, headers } = options;
256171
256252
  verifyDenoInstalled("to run scripts with exec");
256172
256253
  const cleanupFns = [];
256173
256254
  const tempScript = await $file({ postfix: ".ts" });
@@ -256180,9 +256261,10 @@ async function runScript(options) {
256180
256261
  copyFileSync(getExecWrapperPath(), tempWrapper.path);
256181
256262
  try {
256182
256263
  const exitCode = await new Promise((resolvePromise) => {
256183
- const child = spawn4("deno", ["run", "--allow-all", "--node-modules-dir=auto", tempWrapper.path], {
256264
+ const child = spawn4("deno", ["run", "--allow-all", "--node-modules-dir=none", tempWrapper.path], {
256184
256265
  env: {
256185
- ...process.env,
256266
+ ...inheritedEnv(),
256267
+ ...wrapperOnlyEnv(serviceToken, headers),
256186
256268
  SCRIPT_PATH: scriptPath,
256187
256269
  BASE44_APP_ID: appId,
256188
256270
  BASE44_ACCESS_TOKEN: appUserToken,
@@ -256237,6 +256319,10 @@ async function execAction({ app, isNonInteractive }, options) {
256237
256319
  hints: [{ message: "Usage: base44 exec --local --port <port>" }]
256238
256320
  });
256239
256321
  }
256322
+ const envTarget = readExecEnvTarget();
256323
+ if (envTarget && options.local) {
256324
+ throw new InvalidInputError("--local cannot be used when BASE44_EXEC_ACCESS_TOKEN and BASE44_EXEC_SERVER_URL are set.");
256325
+ }
256240
256326
  const noInputError = new InvalidInputError("No input provided. Pipe a script to stdin.", {
256241
256327
  hints: [
256242
256328
  { message: "File: cat ./script.ts | base44 exec" },
@@ -256252,13 +256338,15 @@ async function execAction({ app, isNonInteractive }, options) {
256252
256338
  if (!code.trim()) {
256253
256339
  throw noInputError;
256254
256340
  }
256255
- const local = options.local ? await resolveLocalTarget(options.port !== undefined ? parsePort(options.port) : DEFAULT_DEV_SERVER_PORT) : undefined;
256341
+ const local = envTarget ? { serverUrl: envTarget.serverUrl, token: envTarget.token } : options.local ? await resolveLocalTarget(options.port !== undefined ? parsePort(options.port) : DEFAULT_DEV_SERVER_PORT) : undefined;
256256
256342
  const { exitCode } = await runScript({
256257
256343
  appId: app.id,
256258
256344
  code,
256259
256345
  local,
256260
256346
  privileged: options.privileged,
256261
- dataEnv: options.dataEnv
256347
+ dataEnv: options.dataEnv,
256348
+ serviceToken: envTarget?.serviceToken,
256349
+ headers: envTarget?.headers
256262
256350
  });
256263
256351
  if (exitCode !== 0) {
256264
256352
  process.exitCode = exitCode;
@@ -256266,7 +256354,7 @@ async function execAction({ app, isNonInteractive }, options) {
256266
256354
  return {};
256267
256355
  }
256268
256356
  function getExecCommand() {
256269
- return new Base44Command("exec").description("Run a script with the Base44 SDK pre-authenticated as the current user").option("--local", "Run against the local `base44 dev` server instead of the deployed app").option("--port <number>", `Port the local dev server is on (with --local; defaults to ${DEFAULT_DEV_SERVER_PORT})`).option("--privileged", "Run with admin privileges (bypass RLS). Requires app owner/editor role.").option("--data-env <environment>", "Data environment to run against (e.g. dev, prod)").addHelpText("after", `
256357
+ return new Base44Command("exec", { requireAuth: () => !hasExecEnvTarget() }).description("Run a script with the Base44 SDK pre-authenticated as the current user").option("--local", "Run against the local `base44 dev` server instead of the deployed app").option("--port <number>", `Port the local dev server is on (with --local; defaults to ${DEFAULT_DEV_SERVER_PORT})`).option("--privileged", "Run with admin privileges (bypass RLS). Requires app owner/editor role.").option("--data-env <environment>", "Data environment to run against (e.g. dev, prod)").addHelpText("after", `
256270
256358
  Examples:
256271
256359
  Run a script file:
256272
256360
  $ cat ./script.ts | base44 exec
@@ -256278,7 +256366,14 @@ Examples:
256278
256366
  $ echo "await base44.entities.Task.create({ title: 'seed' })" | base44 exec --local
256279
256367
 
256280
256368
  With privileged access (bypass RLS):
256281
- $ echo "const all = await base44.entities.Task.list()" | base44 exec --privileged`).action(execAction);
256369
+ $ echo "const all = await base44.entities.Task.list()" | base44 exec --privileged
256370
+
256371
+ Environment (for sandboxes and agents; no login or linked project needed):
256372
+ BASE44_EXEC_ACCESS_TOKEN App-user token for the SDK (requires BASE44_EXEC_SERVER_URL)
256373
+ BASE44_EXEC_SERVER_URL SDK server URL (requires BASE44_EXEC_ACCESS_TOKEN)
256374
+ BASE44_EXEC_SERVICE_TOKEN Optional service token, enables base44.asServiceRole
256375
+ BASE44_EXEC_HEADERS Optional JSON object of extra request headers
256376
+ The app id comes from --app-id or BASE44_APP_ID.`).action(execAction);
256282
256377
  }
256283
256378
 
256284
256379
  // src/cli/commands/project/eject.ts
@@ -260490,4 +260585,4 @@ export {
260490
260585
  runCLI
260491
260586
  };
260492
260587
 
260493
- //# debugId=109E5D924CF39A0264756E2164756E21
260588
+ //# debugId=C3C3E1E2D98B8F5064756E2164756E21