@ts-cloud/core 0.5.0 → 0.5.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
@@ -45517,6 +45517,7 @@ function composeServerlessAppTemplate(opts) {
45517
45517
  TSCLOUD_LAMBDA_MODE: mode,
45518
45518
  TSCLOUD_ENV: environment,
45519
45519
  ...app.octane ? { TSCLOUD_OCTANE: "1" } : {},
45520
+ ...app.scheduler === "sub-minute" ? { TSCLOUD_SCHEDULER: "sub-minute" } : {},
45520
45521
  ...cacheEnabled ? { TSCLOUD_CACHE_TABLE: `${slug}-${environment}-cache` } : {},
45521
45522
  ...hasQueue ? { TSCLOUD_QUEUE: queueNames[0] } : {},
45522
45523
  ...app.env ?? {}
@@ -45536,7 +45537,7 @@ function composeServerlessAppTemplate(opts) {
45536
45537
  ]
45537
45538
  }
45538
45539
  } : {};
45539
- function addFunction(logicalId, name, handler8, mode, memory, timeout, reservedConcurrency) {
45540
+ function addFunction(logicalId, name, handler8, mode, memory, timeout, reservedConcurrency, tmp = tmpStorage) {
45540
45541
  resources[`${logicalId}LogGroup`] = {
45541
45542
  Type: "AWS::Logs::LogGroup",
45542
45543
  Properties: { LogGroupName: `/aws/lambda/${name}`, RetentionInDays: 14 }
@@ -45561,17 +45562,17 @@ function composeServerlessAppTemplate(opts) {
45561
45562
  Timeout: timeout,
45562
45563
  Role: Fn2.getAtt("AppRole", "Arn"),
45563
45564
  Environment: { Variables: baseEnv(mode) },
45564
- EphemeralStorage: { Size: tmpStorage },
45565
+ EphemeralStorage: { Size: tmp },
45565
45566
  ...codeProps,
45566
45567
  ...reservedConcurrency !== undefined ? { ReservedConcurrentExecutions: reservedConcurrency } : {},
45567
45568
  ...vpcConfig
45568
45569
  }
45569
45570
  };
45570
45571
  }
45571
- addFunction("HttpFunction", functionNames.http, handlers.http, "http", app.memory ?? 1024, app.timeout ?? 28, app.concurrency);
45572
- addFunction("CliFunction", functionNames.cli, handlers.cli, "cli", app.cliMemory ?? 1024, app.cliTimeout ?? 900);
45572
+ addFunction("HttpFunction", functionNames.http, handlers.http, "http", app.memory ?? 1024, app.timeout ?? 28, app.concurrency, tmpStorage);
45573
+ addFunction("CliFunction", functionNames.cli, handlers.cli, "cli", app.cliMemory ?? 1024, app.cliTimeout ?? 900, undefined, app.cliTmpStorage ?? tmpStorage);
45573
45574
  if (hasQueue)
45574
- addFunction("QueueFunction", functionNames.queue, handlers.queue, "queue", app.queueMemory ?? 1024, app.queueTimeout ?? 120);
45575
+ addFunction("QueueFunction", functionNames.queue, handlers.queue, "queue", app.queueMemory ?? 1024, app.queueTimeout ?? 120, undefined, app.queueTmpStorage ?? tmpStorage);
45575
45576
  resources.HttpApi = {
45576
45577
  Type: "AWS::ApiGatewayV2::Api",
45577
45578
  Properties: {
@@ -45618,6 +45619,59 @@ function composeServerlessAppTemplate(opts) {
45618
45619
  Value: Fn2.getAtt("HttpApi", "ApiEndpoint")
45619
45620
  };
45620
45621
  outputs.HttpApiId = { Description: "HTTP API id", Value: Fn2.ref("HttpApi") };
45622
+ const domains = (Array.isArray(app.domain) ? app.domain : app.domain ? [app.domain] : []).filter(Boolean);
45623
+ if (domains.length) {
45624
+ if (!app.certificateArn && !app.hostedZoneId) {
45625
+ throw new Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");
45626
+ }
45627
+ let certRef = app.certificateArn;
45628
+ if (!certRef) {
45629
+ resources.HttpCertificate = {
45630
+ Type: "AWS::CertificateManager::Certificate",
45631
+ Properties: {
45632
+ DomainName: domains[0],
45633
+ ...domains.length > 1 ? { SubjectAlternativeNames: domains.slice(1) } : {},
45634
+ ValidationMethod: "DNS",
45635
+ DomainValidationOptions: domains.map((d) => ({ DomainName: d, HostedZoneId: app.hostedZoneId }))
45636
+ }
45637
+ };
45638
+ certRef = Fn2.ref("HttpCertificate");
45639
+ }
45640
+ domains.forEach((d, i) => {
45641
+ const dn = `HttpDomain${i}`;
45642
+ resources[dn] = {
45643
+ Type: "AWS::ApiGatewayV2::DomainName",
45644
+ Properties: {
45645
+ DomainName: d,
45646
+ DomainNameConfigurations: [{ CertificateArn: certRef, EndpointType: "REGIONAL" }]
45647
+ }
45648
+ };
45649
+ resources[`HttpApiMapping${i}`] = {
45650
+ Type: "AWS::ApiGatewayV2::ApiMapping",
45651
+ DependsOn: ["HttpStage"],
45652
+ Properties: { ApiId: Fn2.ref("HttpApi"), DomainName: Fn2.ref(dn), Stage: "$default" }
45653
+ };
45654
+ if (app.hostedZoneId) {
45655
+ resources[`HttpDomainRecord${i}`] = {
45656
+ Type: "AWS::Route53::RecordSet",
45657
+ Properties: {
45658
+ HostedZoneId: app.hostedZoneId,
45659
+ Name: d,
45660
+ Type: "A",
45661
+ AliasTarget: {
45662
+ DNSName: Fn2.getAtt(dn, "RegionalDomainName"),
45663
+ HostedZoneId: Fn2.getAtt(dn, "RegionalHostedZoneId")
45664
+ }
45665
+ }
45666
+ };
45667
+ }
45668
+ outputs[`CustomDomain${i}`] = { Description: `Custom domain ${d}`, Value: d };
45669
+ outputs[`CustomDomainTarget${i}`] = {
45670
+ Description: `Point ${d} (CNAME/alias) at this APIGW regional domain`,
45671
+ Value: Fn2.getAtt(dn, "RegionalDomainName")
45672
+ };
45673
+ });
45674
+ }
45621
45675
  if (hasQueue) {
45622
45676
  resources.AppQueueDlq = {
45623
45677
  Type: "AWS::SQS::Queue",
package/dist/types.d.ts CHANGED
@@ -949,6 +949,23 @@ export interface SiteConfig {
949
949
  * process.env.UI_PASSWORD }`. The htpasswd file is generated on the box.
950
950
  */
951
951
  auth?: SiteAuthConfig;
952
+ /**
953
+ * Package-registry credentials written into the release before
954
+ * `composer install` / `npm install` so private packages resolve (Forge's
955
+ * Composer/npm credentials feature).
956
+ */
957
+ credentials?: SiteCredentialsConfig;
958
+ }
959
+ /** Private package-registry credentials for a site's build. */
960
+ export interface SiteCredentialsConfig {
961
+ /**
962
+ * Composer `auth.json` contents — an object (serialized to JSON) or a
963
+ * ready-made JSON string. Written to the release root before `composer
964
+ * install` (e.g. `{ 'github-oauth': { 'github.com': '<token>' } }`).
965
+ */
966
+ composerAuth?: Record<string, unknown> | string;
967
+ /** `.npmrc` contents written to the release root before `npm install`. */
968
+ npmrc?: string;
952
969
  }
953
970
  /** HTTP Basic auth for a site's nginx vhost. See {@link SiteConfig.auth}. */
954
971
  export interface SiteAuthConfig {
@@ -1006,6 +1023,32 @@ export interface SiteSslConfig {
1006
1023
  certPath?: string;
1007
1024
  /** Path to the private key (PEM) when `provider: 'custom'`. */
1008
1025
  keyPath?: string;
1026
+ /**
1027
+ * Issue a **wildcard** certificate (`*.<domain>` + `<domain>`). Requires
1028
+ * DNS-01 validation, so {@link dns} must be set. The nginx plugin can't do
1029
+ * wildcards (that needs HTTP-01 per host).
1030
+ */
1031
+ wildcard?: boolean;
1032
+ /**
1033
+ * Use DNS-01 validation via a certbot DNS plugin instead of the nginx
1034
+ * (HTTP-01) challenge. Needed for wildcard certs and for issuing before the
1035
+ * domain resolves to the box. The plugin + credentials are wired on the box.
1036
+ */
1037
+ dns?: SslDnsConfig;
1038
+ }
1039
+ /** certbot DNS-01 plugin configuration for DNS-validated / wildcard certs. */
1040
+ export interface SslDnsConfig {
1041
+ /** DNS provider whose certbot plugin handles the `_acme-challenge` records. */
1042
+ provider: 'cloudflare' | 'route53' | 'digitalocean' | 'google';
1043
+ /**
1044
+ * Provider credentials written to a root-only INI certbot reads
1045
+ * (`--dns-<provider>-credentials`). For route53, AWS env/instance-role creds
1046
+ * are used instead, so this may be omitted. Keys are provider-specific, e.g.
1047
+ * `{ dns_cloudflare_api_token: '…' }`.
1048
+ */
1049
+ credentials?: Record<string, string>;
1050
+ /** Seconds to wait for DNS propagation before certbot asks the CA to verify. */
1051
+ propagationSeconds?: number;
1009
1052
  }
1010
1053
  /**
1011
1054
  * A Laravel queue worker (or Horizon supervisor) run as a systemd service.
@@ -1123,6 +1166,34 @@ export interface DatabaseConfig {
1123
1166
  host?: string;
1124
1167
  /** Port (defaults: mysql/mariadb 3306, postgres 5432). */
1125
1168
  port?: number;
1169
+ /**
1170
+ * Additional database users to create beyond the app {@link username}
1171
+ * (the Forge Database Users feature). Each can be granted full or read-only
1172
+ * access to one or more databases. Created at provision time on the on-box
1173
+ * engine.
1174
+ */
1175
+ users?: DatabaseUserConfig[];
1176
+ }
1177
+ /**
1178
+ * An extra database user provisioned on the on-box engine (per-user grants).
1179
+ * Beyond the application user, you can create reporting/read-only accounts or
1180
+ * service-specific logins with their own access scope.
1181
+ */
1182
+ export interface DatabaseUserConfig {
1183
+ /** User name to create. */
1184
+ username: string;
1185
+ /** Password for the user. */
1186
+ password: string;
1187
+ /**
1188
+ * Databases this user may access. Defaults to the app database
1189
+ * ({@link DatabaseConfig.name}) when omitted.
1190
+ */
1191
+ databases?: string[];
1192
+ /**
1193
+ * Access level granted on {@link databases}. `all` (default) is full
1194
+ * read/write; `readonly` grants SELECT only (plus connect on Postgres).
1195
+ */
1196
+ access?: 'all' | 'readonly';
1126
1197
  }
1127
1198
  export interface CacheConfig {
1128
1199
  type?: 'redis' | 'memcached';
@@ -1530,8 +1601,12 @@ export interface ServerlessAppConfig {
1530
1601
  rdsProxy?: boolean | {
1531
1602
  name?: string;
1532
1603
  };
1533
- /** Ephemeral `/tmp` size in MB (51210240). @default 512 */
1604
+ /** Ephemeral storage in MB (512 to 10240) for the HTTP function. @default 512 */
1534
1605
  tmpStorage?: number;
1606
+ /** Ephemeral storage in MB for the CLI function. @default tmpStorage */
1607
+ cliTmpStorage?: number;
1608
+ /** Ephemeral storage in MB for the queue function. @default tmpStorage */
1609
+ queueTmpStorage?: number;
1535
1610
  /** Database attachment. */
1536
1611
  database?: {
1537
1612
  connection?: 'rds-proxy' | 'aurora-serverless' | 'rds';
@@ -1548,10 +1623,17 @@ export interface ServerlessAppConfig {
1548
1623
  };
1549
1624
  /** Managed WAF in front of the HTTP API / CloudFront. */
1550
1625
  firewall?: WafConfig;
1551
- /** Custom domain for the app (overrides {@link EnvironmentConfig.domain}). */
1626
+ /** Custom domain(s) for the app's HTTP API (overrides {@link EnvironmentConfig.domain}). */
1552
1627
  domain?: string | string[];
1553
- /** Pre-issued ACM certificate ARN for the custom domain. */
1628
+ /** Pre-issued ACM certificate ARN for the custom domain (regional, same region). */
1554
1629
  certificateArn?: string;
1630
+ /**
1631
+ * Route53 hosted zone ID for the custom domain. When set (and no
1632
+ * `certificateArn`), ts-cloud issues + DNS-validates an ACM cert and creates
1633
+ * the alias record automatically. Without it, supply `certificateArn` and
1634
+ * point your DNS at the API's regional domain (emitted as a stack output).
1635
+ */
1636
+ hostedZoneId?: string;
1555
1637
  /** Local directory whose contents are uploaded to S3/CloudFront as versioned assets. */
1556
1638
  assets?: string;
1557
1639
  /** PHP version for the runtime layer. @default '8.3' */
@@ -3191,7 +3273,7 @@ export interface RealtimeHooksConfig {
3191
3273
  * })
3192
3274
  *
3193
3275
  * // Private channel
3194
- * Echo.private(`user.${userId}`).listen('notification', (e) => {
3276
+ * Echo.private('user.' + userId).listen('notification', (e) => {
3195
3277
  * console.log('Private notification:', e)
3196
3278
  * })
3197
3279
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ts-cloud/core",
3
- "version": "0.5.0",
3
+ "version": "0.5.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.5.0"
34
+ "@ts-cloud/aws-types": "0.5.1"
35
35
  },
36
36
  "devDependencies": {
37
37
  "typescript": "^5.9.3"