@ts-cloud/core 0.3.1 → 0.4.1

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/index.js CHANGED
@@ -25170,7 +25170,8 @@ var cloud_config_schema_default = {
25170
25170
  type: "object",
25171
25171
  description: "Serverless application manifest (Laravel-Vapor-equivalent). Defining this opts the environment into the serverless app deploy pipeline (http/queue/cli Lambda functions, assets, build/deploy hooks).",
25172
25172
  properties: {
25173
- runtime: { type: "string", description: "Lambda runtime (e.g. nodejs20.x, provided.al2023)" },
25173
+ runtime: { type: "string", description: "Lambda runtime override (usually derived from kind + runtimeVersion)" },
25174
+ runtimeVersion: { type: "string", description: "Node major (18/20/22 managed, 24+ custom layer) or Bun release for node/bun apps" },
25174
25175
  kind: { type: "string", enum: ["node", "bun", "php"], description: "Application kind (drives packaging + runtime)" },
25175
25176
  entry: { type: "string", description: "Entry file exporting the request handler" },
25176
25177
  memory: { type: "number", description: "HTTP function memory in MB" },
@@ -45281,7 +45282,7 @@ async function packageServerlessApp(opts) {
45281
45282
  opts.onStep?.("bundling application");
45282
45283
  const result = await Bun.build({
45283
45284
  entrypoints: [bootstrapPath],
45284
- target: "node",
45285
+ target: app.kind === "bun" ? "bun" : "node",
45285
45286
  format: "esm",
45286
45287
  minify: false,
45287
45288
  sourcemap: "none"
@@ -45312,6 +45313,57 @@ ${logs}`);
45312
45313
  rmSync(stage, { recursive: true, force: true });
45313
45314
  }
45314
45315
  }
45316
+ // src/serverless/runtime-resolve.ts
45317
+ var MANAGED_NODE_VERSIONS = ["18", "20", "22"];
45318
+ function normalizeNodeVersion(v) {
45319
+ if (!v)
45320
+ return "22";
45321
+ const m = String(v).match(/(\d+)/);
45322
+ return m ? m[1] : "22";
45323
+ }
45324
+ function resolveServerlessRuntime(app) {
45325
+ const kind = app.kind ?? "node";
45326
+ if (kind === "php") {
45327
+ return {
45328
+ lambdaRuntime: "provided.al2023",
45329
+ kind: "php",
45330
+ version: app.phpVersion ?? "8.3",
45331
+ usesLayer: true,
45332
+ layerKind: "php",
45333
+ layerEnvVar: "TSCLOUD_PHP_LAYER_ARN"
45334
+ };
45335
+ }
45336
+ if (kind === "bun") {
45337
+ return {
45338
+ lambdaRuntime: "provided.al2023",
45339
+ kind: "bun",
45340
+ version: app.runtimeVersion ?? "latest",
45341
+ usesLayer: true,
45342
+ layerKind: "bun",
45343
+ layerEnvVar: "TSCLOUD_BUN_LAYER_ARN"
45344
+ };
45345
+ }
45346
+ const version = normalizeNodeVersion(app.runtimeVersion);
45347
+ const explicitProvided = app.runtime === "provided.al2023";
45348
+ const managed = !explicitProvided && MANAGED_NODE_VERSIONS.includes(version);
45349
+ if (managed) {
45350
+ return {
45351
+ lambdaRuntime: app.runtime && app.runtime.startsWith("nodejs") ? app.runtime : `nodejs${version}.x`,
45352
+ kind: "node",
45353
+ version,
45354
+ usesLayer: false
45355
+ };
45356
+ }
45357
+ return {
45358
+ lambdaRuntime: "provided.al2023",
45359
+ kind: "node",
45360
+ version,
45361
+ usesLayer: true,
45362
+ layerKind: "node",
45363
+ layerEnvVar: "TSCLOUD_NODE_LAYER_ARN"
45364
+ };
45365
+ }
45366
+
45315
45367
  // src/serverless/composer.ts
45316
45368
  function resolveQueueNames(app, slug, env) {
45317
45369
  if (app.queues === false)
@@ -45326,7 +45378,7 @@ function resolveQueueNames(app, slug, env) {
45326
45378
  function composeServerlessAppTemplate(opts) {
45327
45379
  const { app, environment, handlers } = opts;
45328
45380
  const slug = opts.config.project.slug;
45329
- const runtime = app.runtime ?? "nodejs20.x";
45381
+ const runtime = resolveServerlessRuntime(app).lambdaRuntime;
45330
45382
  const architecture = app.architecture ?? "x86_64";
45331
45383
  const region = opts.config.project.region;
45332
45384
  const functionNames = {
@@ -45951,6 +46003,84 @@ COPY app/ \${LAMBDA_TASK_ROOT}/
45951
46003
  CMD [ "index.http" ]
45952
46004
  `;
45953
46005
  }
46006
+ // src/serverless/runtimes/index.ts
46007
+ import { execFileSync } from "node:child_process";
46008
+ import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync4, rmSync as rmSync2 } from "node:fs";
46009
+ import { tmpdir as tmpdir2 } from "node:os";
46010
+ import { dirname as dirname3, join as join7 } from "node:path";
46011
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
46012
+ function assetsDir() {
46013
+ return dirname3(fileURLToPath2(import.meta.url));
46014
+ }
46015
+ function sharedRuntimeLoop() {
46016
+ return readFileSync4(join7(assetsDir(), "runtime.mjs"), "utf-8");
46017
+ }
46018
+ function bootstrap(kind) {
46019
+ return readFileSync4(join7(assetsDir(), `${kind}-bootstrap`), "utf-8");
46020
+ }
46021
+ function buildNodeRuntimeLayerZip(options) {
46022
+ const architecture = options.architecture ?? "x86_64";
46023
+ const nodeArch = architecture === "arm64" ? "arm64" : "x64";
46024
+ const version = options.version.replace(/^v/, "");
46025
+ const step = options.onStep ?? (() => {});
46026
+ const stage = mkdtempSync2(join7(tmpdir2(), "tscloud-node-layer-"));
46027
+ try {
46028
+ const exact = version.includes(".") ? version : resolveLatestNode(version);
46029
+ const dir = `node-v${exact}-linux-${nodeArch}`;
46030
+ const url = `https://nodejs.org/dist/v${exact}/${dir}.tar.xz`;
46031
+ step(`downloading Node ${exact} (${architecture})`);
46032
+ const tar = join7(stage, "node.tar.xz");
46033
+ fetchToFile(url, tar);
46034
+ step("extracting node binary");
46035
+ execFileSync("tar", ["-xf", tar, "-C", stage, `${dir}/bin/node`], { stdio: "inherit" });
46036
+ const nodeBin = readFileSync4(join7(stage, dir, "bin", "node"));
46037
+ step("packaging layer");
46038
+ const entries = [
46039
+ { name: "bootstrap", data: bootstrap("node"), mode: 493 },
46040
+ { name: "runtime.mjs", data: sharedRuntimeLoop(), mode: 420 },
46041
+ { name: "bin/node", data: nodeBin, mode: 493 }
46042
+ ];
46043
+ return { zip: createZip(entries), architecture, version: exact, fileCount: entries.length };
46044
+ } finally {
46045
+ rmSync2(stage, { recursive: true, force: true });
46046
+ }
46047
+ }
46048
+ function buildBunRuntimeLayerZip(options) {
46049
+ const architecture = options.architecture ?? "x86_64";
46050
+ const bunArch = architecture === "arm64" ? "bun-linux-aarch64" : "bun-linux-x64";
46051
+ const version = options.version === "latest" ? "" : options.version.replace(/^v/, "");
46052
+ const step = options.onStep ?? (() => {});
46053
+ const stage = mkdtempSync2(join7(tmpdir2(), "tscloud-bun-layer-"));
46054
+ try {
46055
+ const url = version ? `https://github.com/oven-sh/bun/releases/download/bun-v${version}/${bunArch}.zip` : `https://github.com/oven-sh/bun/releases/latest/download/${bunArch}.zip`;
46056
+ step(`downloading Bun ${version || "latest"} (${architecture})`);
46057
+ const zipPath = join7(stage, "bun.zip");
46058
+ fetchToFile(url, zipPath);
46059
+ step("extracting bun binary");
46060
+ execFileSync("unzip", ["-o", "-q", zipPath, "-d", stage], { stdio: "inherit" });
46061
+ const bunBin = readFileSync4(join7(stage, bunArch, "bun"));
46062
+ step("packaging layer");
46063
+ const entries = [
46064
+ { name: "bootstrap", data: bootstrap("bun"), mode: 493 },
46065
+ { name: "runtime.mjs", data: sharedRuntimeLoop(), mode: 420 },
46066
+ { name: "bin/bun", data: bunBin, mode: 493 }
46067
+ ];
46068
+ return { zip: createZip(entries), architecture, version: version || "latest", fileCount: entries.length };
46069
+ } finally {
46070
+ rmSync2(stage, { recursive: true, force: true });
46071
+ }
46072
+ }
46073
+ function fetchToFile(url, dest) {
46074
+ execFileSync("curl", ["-fsSL", "-o", dest, url], { stdio: ["ignore", "ignore", "inherit"] });
46075
+ }
46076
+ function resolveLatestNode(major) {
46077
+ const indexJson = execFileSync("curl", ["-fsSL", "https://nodejs.org/dist/index.json"], { encoding: "utf-8" });
46078
+ const releases = JSON.parse(indexJson);
46079
+ const match = releases.find((r) => r.version.startsWith(`v${major}.`));
46080
+ if (!match)
46081
+ throw new Error(`No Node release found for major version ${major}`);
46082
+ return match.version.replace(/^v/, "");
46083
+ }
45954
46084
  // src/serverless/runtime/adapter.ts
45955
46085
  function resolveApp(mod) {
45956
46086
  const m = mod;
@@ -46103,15 +46233,15 @@ clear_env = no
46103
46233
  `;
46104
46234
  }
46105
46235
  // src/serverless-php/runtime-assets.ts
46106
- import { readFileSync as readFileSync4 } from "node:fs";
46107
- import { dirname as dirname3, join as join7 } from "node:path";
46108
- import { fileURLToPath as fileURLToPath2 } from "node:url";
46109
- function assetsDir() {
46110
- return join7(dirname3(fileURLToPath2(import.meta.url)), "runtime-assets");
46236
+ import { readFileSync as readFileSync5 } from "node:fs";
46237
+ import { dirname as dirname4, join as join8 } from "node:path";
46238
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
46239
+ function assetsDir2() {
46240
+ return join8(dirname4(fileURLToPath3(import.meta.url)), "runtime-assets");
46111
46241
  }
46112
46242
  function phpRuntimeLayerAssets() {
46113
- const dir = assetsDir();
46114
- const read = (f) => readFileSync4(join7(dir, f), "utf-8");
46243
+ const dir = assetsDir2();
46244
+ const read = (f) => readFileSync5(join8(dir, f), "utf-8");
46115
46245
  return [
46116
46246
  { path: "bootstrap", contents: read("bootstrap"), mode: 493 },
46117
46247
  { path: "tscloud/runtime.php", contents: read("runtime.php"), mode: 420 },
@@ -46147,13 +46277,13 @@ var LARAVEL_SERVERLESS_BUILD_STEPS = [
46147
46277
  "php artisan view:cache"
46148
46278
  ];
46149
46279
  // src/serverless-php/layer-build.ts
46150
- import { execFileSync } from "node:child_process";
46151
- import { existsSync as existsSync5, mkdtempSync as mkdtempSync2, readdirSync as readdirSync5, readFileSync as readFileSync5, rmSync as rmSync2, statSync as statSync3, writeFileSync as writeFileSync4 } from "node:fs";
46152
- import { tmpdir as tmpdir2 } from "node:os";
46153
- import { join as join8, relative as relative2 } from "node:path";
46280
+ import { execFileSync as execFileSync2 } from "node:child_process";
46281
+ import { existsSync as existsSync5, mkdtempSync as mkdtempSync3, readdirSync as readdirSync5, readFileSync as readFileSync6, rmSync as rmSync3, statSync as statSync3, writeFileSync as writeFileSync5 } from "node:fs";
46282
+ import { tmpdir as tmpdir3 } from "node:os";
46283
+ import { join as join9, relative as relative2 } from "node:path";
46154
46284
  function* walk(dir) {
46155
46285
  for (const entry of readdirSync5(dir)) {
46156
- const full = join8(dir, entry);
46286
+ const full = join9(dir, entry);
46157
46287
  if (statSync3(full).isDirectory())
46158
46288
  yield* walk(full);
46159
46289
  else
@@ -46164,19 +46294,19 @@ function buildPhpRuntimeLayerZip(options = {}) {
46164
46294
  const architecture = options.architecture ?? "x86_64";
46165
46295
  const platform = options.platform ?? (architecture === "arm64" ? "linux/arm64" : "linux/amd64");
46166
46296
  const step = options.onStep ?? (() => {});
46167
- const stage = mkdtempSync2(join8(tmpdir2(), "tscloud-php-layer-"));
46297
+ const stage = mkdtempSync3(join9(tmpdir3(), "tscloud-php-layer-"));
46168
46298
  const imageTag = "tscloud-php-layer:build";
46169
46299
  try {
46170
- writeFileSync4(join8(stage, "Dockerfile"), generatePhpLayerDockerfile(options));
46300
+ writeFileSync5(join9(stage, "Dockerfile"), generatePhpLayerDockerfile(options));
46171
46301
  step("Building PHP runtime image (docker)");
46172
- execFileSync("docker", ["build", "--platform", platform, "-t", imageTag, stage], { stdio: "inherit" });
46302
+ execFileSync2("docker", ["build", "--platform", platform, "-t", imageTag, stage], { stdio: "inherit" });
46173
46303
  step("Extracting /opt from image");
46174
- const cid = execFileSync("docker", ["create", "--platform", platform, imageTag], { encoding: "utf-8" }).trim();
46175
- const optDir = join8(stage, "opt");
46304
+ const cid = execFileSync2("docker", ["create", "--platform", platform, imageTag], { encoding: "utf-8" }).trim();
46305
+ const optDir = join9(stage, "opt");
46176
46306
  try {
46177
- execFileSync("docker", ["cp", `${cid}:/opt/.`, optDir], { stdio: "inherit" });
46307
+ execFileSync2("docker", ["cp", `${cid}:/opt/.`, optDir], { stdio: "inherit" });
46178
46308
  } finally {
46179
- execFileSync("docker", ["rm", cid], { stdio: "ignore" });
46309
+ execFileSync2("docker", ["rm", cid], { stdio: "ignore" });
46180
46310
  }
46181
46311
  if (!existsSync5(optDir))
46182
46312
  throw new Error("layer build produced no /opt directory");
@@ -46184,7 +46314,7 @@ function buildPhpRuntimeLayerZip(options = {}) {
46184
46314
  for (const file of walk(optDir)) {
46185
46315
  const rel = relative2(optDir, file).replace(/\\/g, "/");
46186
46316
  const mode = statSync3(file).mode & 73 ? 493 : 420;
46187
- entries.push({ name: rel, data: readFileSync5(file), mode });
46317
+ entries.push({ name: rel, data: readFileSync6(file), mode });
46188
46318
  }
46189
46319
  step("Injecting runtime assets");
46190
46320
  const assetPaths = new Set(phpRuntimeLayerAssets().map((a) => a.path));
@@ -46196,14 +46326,14 @@ function buildPhpRuntimeLayerZip(options = {}) {
46196
46326
  const zip2 = createZip(filtered);
46197
46327
  return { zip: zip2, architecture, fileCount: filtered.length };
46198
46328
  } finally {
46199
- rmSync2(stage, { recursive: true, force: true });
46329
+ rmSync3(stage, { recursive: true, force: true });
46200
46330
  }
46201
46331
  }
46202
46332
  // src/serverless-php/package-php.ts
46203
46333
  import { execSync as execSync2 } from "node:child_process";
46204
46334
  import { createHash as createHash5 } from "node:crypto";
46205
- import { readdirSync as readdirSync6, readFileSync as readFileSync6, statSync as statSync4 } from "node:fs";
46206
- import { join as join9, relative as relative3, resolve as resolve2 } from "node:path";
46335
+ import { readdirSync as readdirSync6, readFileSync as readFileSync7, statSync as statSync4 } from "node:fs";
46336
+ import { join as join10, relative as relative3, resolve as resolve2 } from "node:path";
46207
46337
  var PHP_DEFAULT_EXCLUDES = [
46208
46338
  ".git",
46209
46339
  ".github",
@@ -46224,7 +46354,7 @@ function isExcluded(rel, excludes) {
46224
46354
  }
46225
46355
  function* walk2(dir, root, excludes) {
46226
46356
  for (const entry of readdirSync6(dir)) {
46227
- const full = join9(dir, entry);
46357
+ const full = join10(dir, entry);
46228
46358
  const rel = relative3(root, full).replace(/\\/g, "/");
46229
46359
  if (isExcluded(rel, excludes))
46230
46360
  continue;
@@ -46251,7 +46381,7 @@ function collectPhpAppEntries(projectRoot, exclude = []) {
46251
46381
  for (const file of walk2(root, root, excludes)) {
46252
46382
  const rel = relative3(root, file).replace(/\\/g, "/");
46253
46383
  const executable = (statSync4(file).mode & 73) !== 0;
46254
- entries.push({ name: rel, data: readFileSync6(file), mode: executable ? 493 : 420 });
46384
+ entries.push({ name: rel, data: readFileSync7(file), mode: executable ? 493 : 420 });
46255
46385
  }
46256
46386
  return entries;
46257
46387
  }
@@ -46743,6 +46873,7 @@ export {
46743
46873
  stackDependencyManager,
46744
46874
  signRequestAsync,
46745
46875
  signRequest,
46876
+ sharedRuntimeLoop,
46746
46877
  sha256,
46747
46878
  serviceMeshManager,
46748
46879
  sequence,
@@ -46763,6 +46894,7 @@ export {
46763
46894
  resolveSiteStackName,
46764
46895
  resolveSiteResourceName,
46765
46896
  resolveSiteBucketName,
46897
+ resolveServerlessRuntime,
46766
46898
  resolveServerlessAssetBucketName,
46767
46899
  resolveServerlessArtifactBucketName,
46768
46900
  resolveServerlessAppStackName,
@@ -46952,7 +47084,9 @@ export {
46952
47084
  canaryManager,
46953
47085
  buildPhpRuntimeLayerZip,
46954
47086
  buildOptimizationManager,
47087
+ buildNodeRuntimeLayerZip,
46955
47088
  buildCloudFormationTemplate,
47089
+ buildBunRuntimeLayerZip,
46956
47090
  bounceComplaintHandler,
46957
47091
  blueGreenManager,
46958
47092
  batchProcessingManager,
@@ -47033,6 +47167,7 @@ export {
47033
47167
  MigrationManager,
47034
47168
  MetricsManager,
47035
47169
  Messaging,
47170
+ MANAGED_NODE_VERSIONS,
47036
47171
  LogsManager,
47037
47172
  LambdaVersionsManager,
47038
47173
  LambdaVPCManager,
@@ -7,4 +7,6 @@ export * from './bootstrap';
7
7
  export * from './package';
8
8
  export * from './composer';
9
9
  export * from './app-image';
10
+ export * from './runtime-resolve';
11
+ export * from './runtimes';
10
12
  export * from './runtime/adapter';
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Resolves the Lambda runtime for a serverless app from its `kind` +
3
+ * `runtimeVersion`, deciding between an AWS **managed** Node runtime (zero
4
+ * config, no layer) and a **custom** `provided.al2023` runtime backed by a
5
+ * ts-cloud-built layer (binary + bootstrap + Runtime API loop).
6
+ *
7
+ * This unifies all three runtimes under one model: PHP, Bun, and newer Node
8
+ * versions all run on `provided.al2023` with a ts-cloud layer, while common Node
9
+ * versions stay on the managed runtime for simplicity.
10
+ */
11
+ import type { ServerlessAppConfig } from '../types';
12
+ /** Node major versions AWS provides a managed runtime for (`nodejs{N}.x`). */
13
+ export declare const MANAGED_NODE_VERSIONS: readonly ["18", "20", "22"];
14
+ export type RuntimeLayerKind = 'node' | 'bun' | 'php';
15
+ export interface ResolvedRuntime {
16
+ /** The Lambda `Runtime` value (e.g. `nodejs22.x` or `provided.al2023`). */
17
+ lambdaRuntime: string;
18
+ /** Application kind. */
19
+ kind: 'node' | 'bun' | 'php';
20
+ /** Resolved version string (node major / bun release / php version). */
21
+ version: string;
22
+ /** Whether a ts-cloud custom runtime layer is required. */
23
+ usesLayer: boolean;
24
+ /** Which layer to build/attach when {@link usesLayer}. */
25
+ layerKind?: RuntimeLayerKind;
26
+ /** Env var name the orchestrator reads for a fallback layer ARN. */
27
+ layerEnvVar?: string;
28
+ }
29
+ /**
30
+ * Resolve the runtime for an app. Honors an explicit `runtime` override; falls
31
+ * back to deriving from `kind`/`runtimeVersion`.
32
+ */
33
+ export declare function resolveServerlessRuntime(app: ServerlessAppConfig): ResolvedRuntime;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Unified custom-runtime (`provided.al2023`) layer builders for Node and Bun.
3
+ *
4
+ * Both ship the same shape as the PHP runtime layer — a binary + a `bootstrap`
5
+ * entrypoint + the shared {@link runtime.mjs} Runtime API loop — so newer Node
6
+ * versions (e.g. 24, beyond AWS's managed runtimes) and Bun run on Lambda the
7
+ * same way Laravel/PHP does. Unlike the PHP layer these need no Docker: the
8
+ * official binary is downloaded and zipped directly.
9
+ */
10
+ export type RuntimeArch = 'x86_64' | 'arm64';
11
+ /** The shared Runtime API loop source (bundled into every node/bun layer). */
12
+ export declare function sharedRuntimeLoop(): string;
13
+ export interface BuildRuntimeLayerOptions {
14
+ /** Runtime version (Node major like '24', or a Bun release like '1.3.13'). */
15
+ version: string;
16
+ /** Target architecture. @default 'x86_64' */
17
+ architecture?: RuntimeArch;
18
+ /** Progress callback. */
19
+ onStep?: (message: string) => void;
20
+ }
21
+ export interface RuntimeLayerArtifact {
22
+ zip: Buffer;
23
+ architecture: RuntimeArch;
24
+ version: string;
25
+ fileCount: number;
26
+ }
27
+ /**
28
+ * Build the Node custom-runtime layer (any Node version, incl. those without an
29
+ * AWS managed runtime such as 24). Downloads the official linux build and
30
+ * assembles `bootstrap` + `runtime.mjs` + `bin/node`.
31
+ */
32
+ export declare function buildNodeRuntimeLayerZip(options: BuildRuntimeLayerOptions): RuntimeLayerArtifact;
33
+ /**
34
+ * Build the Bun custom-runtime layer. Downloads the pinned Bun release and
35
+ * assembles `bootstrap` + `runtime.mjs` + `bin/bun`.
36
+ */
37
+ export declare function buildBunRuntimeLayerZip(options: BuildRuntimeLayerOptions): RuntimeLayerArtifact;
@@ -0,0 +1 @@
1
+ export {};
package/dist/types.d.ts CHANGED
@@ -1422,11 +1422,24 @@ export interface FunctionConfig {
1422
1422
  */
1423
1423
  export interface ServerlessAppConfig {
1424
1424
  /**
1425
- * Lambda runtime shared by all three functions.
1426
- * Use `provided.al2023` for PHP (custom runtime layer) or Bun custom runtimes.
1427
- * @default 'nodejs20.x'
1425
+ * Explicit Lambda runtime override. Usually you don't set this — it's derived
1426
+ * from {@link kind} + {@link runtimeVersion}:
1427
+ * - `node` on a managed version → `nodejs{18,20,22}.x`
1428
+ * - `node` on a non-managed version (e.g. 24), `bun`, or `php` →
1429
+ * `provided.al2023` with a ts-cloud-built custom runtime layer
1430
+ *
1431
+ * Set this to force a specific value (e.g. `provided.al2023` to run Node on a
1432
+ * custom layer even for a managed version).
1433
+ * @default derived from kind/runtimeVersion
1434
+ */
1435
+ runtime?: 'nodejs18.x' | 'nodejs20.x' | 'nodejs22.x' | 'provided.al2023' | (string & {});
1436
+ /**
1437
+ * Runtime version for `node`/`bun` apps (PHP uses {@link phpVersion}).
1438
+ * - node: '18' | '20' | '22' (managed) or '24'+ (custom provided.al2023 layer)
1439
+ * - bun: a Bun release, e.g. '1.3.13' (always a custom provided.al2023 layer)
1440
+ * @default node '22', bun the layer's pinned default
1428
1441
  */
1429
- runtime?: 'nodejs20.x' | 'nodejs22.x' | 'provided.al2023' | (string & {});
1442
+ runtimeVersion?: string;
1430
1443
  /**
1431
1444
  * Application kind. Drives packaging + runtime selection.
1432
1445
  * - `node` / `bun`: bundle a JS/TS handler artifact
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ts-cloud/core",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "type": "module",
5
5
  "description": "Core CloudFormation generation library for ts-cloud",
6
6
  "author": "Chris Breuer <chris@stacksjs.com>",
@@ -31,7 +31,7 @@
31
31
  "typecheck": "tsc --noEmit"
32
32
  },
33
33
  "dependencies": {
34
- "@ts-cloud/aws-types": "0.3.1"
34
+ "@ts-cloud/aws-types": "0.4.1"
35
35
  },
36
36
  "devDependencies": {
37
37
  "typescript": "^5.9.3"