@videan/cli 0.3.1 → 0.4.0

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 CHANGED
@@ -16,6 +16,11 @@ videan secrets set KEY=value
16
16
  videan apps list
17
17
  ```
18
18
 
19
+ Apps run as a **container** (default: always on) or **serverless** (scales to
20
+ zero, cold start after idle): `videan apps create --mode serverless`, or switch
21
+ later with `videan apps set --mode …` — applied by the next deploy. Serverless
22
+ refuses cron, background jobs, WebSockets and custom Dockerfiles.
23
+
19
24
  The deployed contract is **expose an HTTP port on 3000**. Runtime (Node,
20
25
  Python, Next.js, Go, or your own Dockerfile) is detected from the files.
21
26
  Every deploy is an immutable snapshot; production is a pointer to one.
package/dist/index.js CHANGED
@@ -14,6 +14,9 @@ import os from "node:os";
14
14
  var DEFAULT_API_URL = "https://api.videan.xyz/v1";
15
15
  var APP_DOMAIN = process.env.CLOUD_APP_DOMAIN || "videan.xyz";
16
16
  var MAX_FILE_SIZE_BYTES = 50 * 1024 * 1024;
17
+ var APP_PORT = 3e3;
18
+ var LAMBDA_ADAPTER = `COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.1 /lambda-adapter /opt/extensions/lambda-adapter
19
+ ENV AWS_LWA_PORT=${APP_PORT}`;
17
20
  var FARGATE_SIZES = {
18
21
  256: { min: 512, max: 2048, step: 512 },
19
22
  512: { min: 1024, max: 4096, step: 1024 },
@@ -170,7 +173,9 @@ var AppsNamespace = class {
170
173
  storage_enabled: opts.storage,
171
174
  email_enabled: opts.email,
172
175
  auth_required: opts.authRequired,
173
- visibility: opts.visibility
176
+ visibility: opts.visibility,
177
+ stack: opts.stack,
178
+ mode: opts.mode
174
179
  };
175
180
  const res = await this.client.request("POST", "/apps", body);
176
181
  return res.data;
@@ -199,6 +204,8 @@ var AppsNamespace = class {
199
204
  if (changes.postgres !== void 0) body.postgres_enabled = changes.postgres;
200
205
  if (changes.storage !== void 0) body.storage_enabled = changes.storage;
201
206
  if (changes.email !== void 0) body.email_enabled = changes.email;
207
+ if (changes.stack !== void 0) body.stack = changes.stack;
208
+ if (changes.mode !== void 0) body.mode = changes.mode;
202
209
  const res = await this.client.request(
203
210
  "PATCH",
204
211
  `/apps/${appId}`,
@@ -677,6 +684,12 @@ var OrgsNamespace = class {
677
684
  }
678
685
  };
679
686
 
687
+ // ../shared/src/types.ts
688
+ var APP_MODES = ["container", "serverless"];
689
+ function isAppMode(value) {
690
+ return APP_MODES.includes(value);
691
+ }
692
+
680
693
  // ../shared/src/constants.ts
681
694
  var SUPPORTED_RUNTIMES = [
682
695
  "node-20",
@@ -694,6 +707,11 @@ function appUrl(slug) {
694
707
  var CONFIG_FILE_NAME = "cloud.yaml";
695
708
  var MAX_FILE_SIZE_BYTES2 = 50 * 1024 * 1024;
696
709
 
710
+ // ../shared/src/detect.ts
711
+ var APP_PORT2 = 3e3;
712
+ var LAMBDA_ADAPTER2 = `COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.1 /lambda-adapter /opt/extensions/lambda-adapter
713
+ ENV AWS_LWA_PORT=${APP_PORT2}`;
714
+
697
715
  // ../shared/src/sizing.ts
698
716
  var FARGATE_SIZES2 = {
699
717
  256: { min: 512, max: 2048, step: 512 },
@@ -965,6 +983,15 @@ This platform puts a sign-in gate in front of apps unless they are public.
965
983
 
966
984
  Secrets: \`videan secrets set KEY=value\` (UPPERCASE keys) \u2014 injected as env
967
985
  vars on the next deploy. Never commit credentials to this repo instead.
986
+
987
+ ## Execution modes
988
+
989
+ Apps run as a **container** (default: always on, no cold starts) or
990
+ **serverless** (scales to zero, cold start after idle \u2014 good for internal
991
+ tools with sporadic traffic). Set at create (\`videan apps create --mode
992
+ serverless\`) or later (\`videan apps set --mode \u2026\`, applied by the next
993
+ deploy). Serverless refuses cron, background jobs, WebSockets and custom
994
+ Dockerfiles; container mode supports all of them.
968
995
  `;
969
996
  var POINTER = "\n## Videan\n\nThis project deploys to Videan \u2014 see VIDEAN.md for the platform contract (port 3000, auth headers, deploy commands) before writing server or login code.\n";
970
997
  async function writeVideanMd(dir) {
@@ -1503,6 +1530,15 @@ function accessOption(value) {
1503
1530
  }
1504
1531
  return tier;
1505
1532
  }
1533
+ function modeOption(value) {
1534
+ if (value === void 0) return void 0;
1535
+ const mode = value.trim().toLowerCase();
1536
+ if (!isAppMode(mode)) {
1537
+ console.error(chalk11.red(`Unknown --mode value "${value}". Use one of: ${APP_MODES.join(", ")}`));
1538
+ process.exit(1);
1539
+ }
1540
+ return mode;
1541
+ }
1506
1542
  function describeAccess(app) {
1507
1543
  const tier = app.visibility ? visibilityOf(app.visibility) : app.authRequired ? "org" : "public";
1508
1544
  return `${tier} \u2014 ${VISIBILITY_LABELS[tier].toLowerCase()}`;
@@ -1523,7 +1559,13 @@ appsCommand.command("list").description("List all apps").option("-o, --org <id>"
1523
1559
  console.log(formatRow([app.name, app.id, app.status, appUrl(app.slug)], widths));
1524
1560
  }
1525
1561
  });
1526
- appsCommand.command("create").description("Create a new app").option("-n, --name <name>", "App name").option("-o, --org <id>", "Organization ID").option("--postgres", "Provision a managed Postgres database").option("--storage", "Give the app an object-storage prefix").option("--email", "Let the app send mail through the platform").option("--public", "Serve the app without the platform login gate (same as --access public)").option("--access <tier>", `Who may open the app: ${VISIBILITIES.join(" | ")} (default: ${DEFAULT_VISIBILITY})`).action(
1562
+ appsCommand.command("create").description("Create a new app").option("-n, --name <name>", "App name").option("-o, --org <id>", "Organization ID").option("--postgres", "Provision a managed Postgres database").option("--storage", "Give the app an object-storage prefix").option("--email", "Let the app send mail through the platform").option("--public", "Serve the app without the platform login gate (same as --access public)").option("--access <tier>", `Who may open the app: ${VISIBILITIES.join(" | ")} (default: ${DEFAULT_VISIBILITY})`).option(
1563
+ "--stack <label>",
1564
+ "Group this app with its siblings (set the same label on a split frontend and backend)"
1565
+ ).option(
1566
+ "--mode <mode>",
1567
+ `How the app runs: ${APP_MODES.join(" | ")} (default: container). serverless scales to zero but runs no cron, jobs or WebSockets`
1568
+ ).action(
1527
1569
  async (opts) => {
1528
1570
  const apiKey = getApiKey();
1529
1571
  requireApiKey(apiKey);
@@ -1540,6 +1582,7 @@ appsCommand.command("create").description("Create a new app").option("-n, --name
1540
1582
  process.exit(1);
1541
1583
  }
1542
1584
  const visibility = accessOption(opts.access) ?? (opts.public ? "public" : void 0);
1585
+ const mode = modeOption(opts.mode);
1543
1586
  const client4 = new CloudClient({ apiKey, baseUrl: getBaseUrl() });
1544
1587
  const app = await client4.apps.create({
1545
1588
  name,
@@ -1547,16 +1590,19 @@ appsCommand.command("create").description("Create a new app").option("-n, --name
1547
1590
  postgres: opts.postgres ?? false,
1548
1591
  storage: opts.storage ?? false,
1549
1592
  email: opts.email ?? false,
1550
- visibility
1593
+ visibility,
1594
+ stack: opts.stack,
1595
+ mode
1551
1596
  });
1552
1597
  setCurrentApp(app.id);
1553
1598
  console.log(chalk11.green(`App "${app.name}" created (${app.id})`));
1599
+ console.log(chalk11.gray(` Mode: ${app.mode ?? "container"}`));
1554
1600
  console.log(chalk11.gray(` Access: ${describeAccess(app)}`));
1555
1601
  console.log(chalk11.gray(` URL after first deploy: ${appUrl(app.slug)}`));
1556
1602
  console.log(chalk11.gray(" Push code with `videan deploy` \u2014 the runtime is auto-detected."));
1557
1603
  }
1558
1604
  );
1559
- appsCommand.command("set").description("Change an app's settings (scale, rate limit, gate, capabilities)").option("-a, --app <id>", "App ID").option("-n, --name <name>", "Rename the app (the URL keeps its original slug)").option("--cpu <units>", "CPU units per instance (256 = 0.25 vCPU)").option("--memory <mib>", "Memory per instance, in MiB").option("--instances <n>", "Number of instances to run").option("--rate-limit <rpm>", "Requests per minute per client").option("--no-rate-limit", "Remove the rate limit").option("--access <tier>", `Who may open the app: ${VISIBILITIES.join(" | ")}`).option("--public", "Serve without the platform login gate (same as --access public)").option("--private", "Require platform login (leaves the tier alone if it is already gated)").option("--postgres", "Provision a managed Postgres database").option("--storage", "Give the app an object-storage prefix").option("--email", "Let the app send mail through the platform").option("--json", "Print the raw response").action(
1605
+ appsCommand.command("set").description("Change an app's settings (scale, rate limit, gate, capabilities)").option("-a, --app <id>", "App ID").option("-n, --name <name>", "Rename the app (the URL keeps its original slug)").option("--cpu <units>", "CPU units per instance (256 = 0.25 vCPU)").option("--memory <mib>", "Memory per instance, in MiB").option("--instances <n>", "Number of instances to run").option("--rate-limit <rpm>", "Requests per minute per client").option("--no-rate-limit", "Remove the rate limit").option("--access <tier>", `Who may open the app: ${VISIBILITIES.join(" | ")}`).option("--public", "Serve without the platform login gate (same as --access public)").option("--private", "Require platform login (leaves the tier alone if it is already gated)").option("--postgres", "Provision a managed Postgres database").option("--storage", "Give the app an object-storage prefix").option("--email", "Let the app send mail through the platform").option("--stack <label>", "Group this app with its siblings under a shared label").option("--no-stack", "Remove the app from its stack").option("--mode <mode>", `How the app runs: ${APP_MODES.join(" | ")} (applies on the next deploy or restart)`).option("--json", "Print the raw response").action(
1560
1606
  async (opts) => {
1561
1607
  const apiKey = getApiKey();
1562
1608
  requireApiKey(apiKey);
@@ -1574,8 +1620,10 @@ appsCommand.command("set").description("Change an app's settings (scale, rate li
1574
1620
  console.error(chalk11.red("--access already says who may open the app; drop --public/--private."));
1575
1621
  process.exit(1);
1576
1622
  }
1623
+ const mode = modeOption(opts.mode);
1577
1624
  const changes = {};
1578
1625
  if (opts.name) changes.name = opts.name;
1626
+ if (mode) changes.mode = mode;
1579
1627
  if (opts.cpu !== void 0) changes.cpu = intOption("--cpu", opts.cpu);
1580
1628
  if (opts.memory !== void 0) changes.memory = intOption("--memory", opts.memory);
1581
1629
  if (opts.instances !== void 0) {
@@ -1591,6 +1639,8 @@ appsCommand.command("set").description("Change an app's settings (scale, rate li
1591
1639
  if (opts.postgres) changes.postgres = true;
1592
1640
  if (opts.storage) changes.storage = true;
1593
1641
  if (opts.email) changes.email = true;
1642
+ if (opts.stack === false) changes.stack = null;
1643
+ else if (typeof opts.stack === "string") changes.stack = opts.stack;
1594
1644
  if (Object.keys(changes).length === 0) {
1595
1645
  console.error(chalk11.red("Nothing to change. Pass at least one option."));
1596
1646
  process.exit(1);
@@ -1602,6 +1652,7 @@ appsCommand.command("set").description("Change an app's settings (scale, rate li
1602
1652
  return;
1603
1653
  }
1604
1654
  console.log(chalk11.green(`Updated ${app.name} (${app.id})`));
1655
+ console.log(` Mode: ${app.mode ?? "container"}`);
1605
1656
  console.log(` Access: ${describeAccess(app)}`);
1606
1657
  console.log(` Scale: ${app.cpu ?? "default"} CPU / ${app.memory ?? "default"} MiB`);
1607
1658
  console.log(
@@ -2237,7 +2288,7 @@ function period(start, end) {
2237
2288
 
2238
2289
  // src/index.ts
2239
2290
  var program = new Command18();
2240
- program.name("videan").description("Videan CLI \u2014 deploy apps in seconds").version("0.1.0");
2291
+ program.name("videan").description("Videan CLI \u2014 deploy apps in seconds").version("0.4.0");
2241
2292
  program.addCommand(loginCommand);
2242
2293
  program.addCommand(logoutCommand);
2243
2294
  program.addCommand(initCommand);